天天看點

JAVA多線程之——線程之間的通信

概要

我們知道線程是作業系統中一個獨立的個體,在一般多線程環境下,我們希望的是各個線程之間有一定的關聯,使得各個線程組合成一個整體工作。那麼就必須要使線程之間互相能傳遞資訊。這就是線程之間需要通信。線程通信可以采取wait/notify 方法實作通信(當然還有其它通信方式。這節隻學習wait/notify 方法)。

wait/notify定義

1.wait/notify方法定義在Object類中。這說明JAVA中多有對象都擁有wait/notify方法。那麼為什麼wait/notify方法是用來實作線程之間的通信,為何不定義在Thread中呢?首先看一下源碼:

/**The current thread must own this object's monitor. The thread
     * releases ownership of this monitor and waits until another thread
     * notifies threads waiting on this object's monitor to wake up
     * */
    public final void wait() throws InterruptedException {
        wait();
    }
官方文檔中開頭的一段解釋就是,使用wait方法,那麼目前的線程必須要是某個對象的監控者。換句話說,就是要使用wait方法就必須要擁有某個對象的鎖。也就是說wait/notify依賴于對象鎖。而鎖可以是任意一個對象都可以擁有。那麼就意味着必須任意的對象都可以調用wait/notify方法。那麼這些方法就隻能定義在Object中。


**wait/notify使用**
           

public class ThreadTest3 {

private volatile int i = 0;

public void method1() {
    i++;
}

public int getI() {

    return i;

}

public static void main(String[] args) {

    final ThreadTest3 test3 = new ThreadTest3();

    final Object lock = new Object();

    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            synchronized (lock) {
                try {
                    for (int k = 0; k < 10; k++) {
                        test3.method1();
                        System.out.println("i自增1 ");
                        if (test3.getI() == 5) {
                            System.out.println("發出通知。。。。。。");
                             lock.notify();
                        }
                        Thread.currentThread().sleep(500);
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }

    }, "t1");

    Thread t2 = new Thread(new Runnable() {
        @Override
        public void run() {
                    synchronized (lock) {
                        if(test3.getI() != 5) {
                            try {
                                lock.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }

                System.out.println("收到通知。。。。。。。。。停止工作");
                throw new RuntimeException();
            }


    }, "t2");

    t2.start();
    t1.start();

}
           

}

上述代碼運作結果:
           

i自增1

i自增1

i自增1

i自增1

i自增1

發出通知。。。。。。

i自增1

i自增1

i自增1

i自增1

i自增1

收到通知。。。。。。。。。停止工作

Exception in thread “t2” java.lang.RuntimeException

at thread.day2.ThreadTest3$2.run(ThreadTest3.java:61)

at java.lang.Thread.run(Thread.java:745)

“`

結果分析:當我們啟動先啟動t2線程時候,擷取了lock的鎖,第一次進去i不等與5,t2調用wait方法進入等待,然後t1擷取lock同步鎖,對i進行自增,在等于5的時候,發出通知調用notify方法。但運作的結果是知道t1運作完成後。t2才執行了停止工作。

結果總結:

1.wait釋放所。并且wait方法是停止目前擁有該對象同步鎖的線程

2.notify不釋放鎖