Java多線程基礎 線程的等待與喚醒

lamberta 7年前發布 | 24K 次閱讀 多線程 Java Java開發

題圖:花啡,豆是買咖啡機送的,花是上周陽朔旅游買的桂花,給它起了個名字,叫 Sunday。

咖啡味淡了一點點,多了一份桂花的清香。

本篇我們來研究一下 wait() notify() notifyAll() 。

DEMO1: wait() 與 notify()

public class Test {

    static class ThreadOne extends Thread {

        private Callback mCallback;

        @Override
        public void run() {
            work();
            if (mCallback != null) {
                mCallback.onResult(false);
            }
        }

        // 耗時 3s
        private void work() {
            System.out.println(" 正在查詢數據庫 1");
            long startTime = System.currentTimeMillis();
            while (true) {
                if (System.currentTimeMillis() - startTime < 3000) {
                    continue;
                }
                break;
            }
        }

        public void setCallback(Callback callback) {
            mCallback = callback;
        }

        public interface Callback {
            void onResult(boolean result);
        }
    }

    static class ThreadTest extends Thread {

        private Object mLock = new Object();

        private ThreadOne mThreadOne;

        @Override
        public void run() {
            workOne();
            System.out.println(" 根據結果繼續做其他事情 ");
        }

        private void workOne() {
            mThreadOne = new ThreadOne();
            mThreadOne.setCallback(new ThreadOne.Callback() {
                @Override
                public void onResult(boolean result) {
                    System.out.println(" 查詢數據庫 1 結束,:" + (result ? " 有數據 " : " 無數據 "));
                    synchronized (mLock) {
                        mLock.notify();
                        System.out.println("--ThreadTest 結束等待 --");
                    }
                }
            });
            mThreadOne.start();
            try {
                synchronized (mLock) {
                    System.out.println("--ThreadTest 進入等待 --");
                    mLock.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] var0) {
        ThreadTest threadTest = new ThreadTest();
        threadTest.start();
    }
}

DEMO1 輸出:

--ThreadTest 進入等待--
正在查詢數據庫 1
查詢數據庫 1 結束,: 無數據
--ThreadTest 結束等待--
根據結果繼續做其他事情

注意:

使用 wait() 和 notify() 必須在獲得同步鎖后才能調用,若直接調用會報 java.lang.IllegalMonitorStateException 錯誤,因為狀態由同步鎖保護。

wait() 不同于 sleep() 的是 wait() 會釋放同步鎖。

因為 wait() 和 notify() 是基于同步鎖實現的,每個對象都有自己的同步鎖,所以 wait() 和 notify() 是 Object 的方法,而不是 Thread。

DEMO2,wait() 與 notifyAll():

public class Test {

    private static Object mLock = new Object();

    static class MyThread extends Thread {

        String mName;
        Callback mCallback;

        public MyThread(String name){
            mName = name;
        }

        @Override
        public void run() {
            work();
            if (mCallback != null) {
                mCallback.onResult(false);
            }
        }

        // 耗時 3s
        private void work() {
            System.out.println(mName + " 等待 ");
            try {
                synchronized (mLock) {
                    mLock.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        public void setCallback(Callback callback) {
            mCallback = callback;
        }

        public interface Callback {
            void onResult(boolean result);
        }
    }

    static class ThreadTest extends Thread {



        @Override
        public void run() {
            work("db1");
            work("db2");
            work("db3");

            try {
                sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            synchronized (mLock) {
                System.out.println(" 喚醒全部 ");
                mLock.notifyAll();
            }
        }

        private void work(String name) {
            final MyThread myThread = new MyThread(name);
            myThread.setCallback(new MyThread.Callback() {
                @Override
                public void onResult(boolean result) {
                    System.out.println(myThread.mName + " 回來了 ");
                }
            });
            myThread.start();
        }
    }

    public static void main(String[] var0) {
        ThreadTest threadTest = new ThreadTest();
        threadTest.start();
    }
}

DEMO2 輸出:

db1 等待
db3 等待
db2 等待
喚醒全部
db3 回來了
db1 回來了
db2 回來了

同一個對象的 wait() 方法可多次在不同的線程中調用,可讓不同的線程進入等待(阻塞),可以一個一個 notify(),也可以調用 notifyAll() 一次性全部喚醒。

 

來自:http://hackeris.me/2017/05/07/thread_base_1/

 

 本文由用戶 lamberta 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!