天天看點

Java線程之間通信與協作

在Java多線程情況下,線程之間可能存在執行的先後順序,那麼線程之間是如何實作通信的呢?

join()

當在一個線程中調用了另一個線程的join()方法時,目前線程将會挂起(不是自旋),直到目标線程執行結束。

public class JoinClass {
    private class A extends Thread {
        @Override
        public void run() {
            System.out.println("A");
        }
    }
 
    private class B extends Thread {
        private A a;
        B(A a) {
            this.a = a;
        }
 
        @Override
        public void run() {
            try {
                a.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("B");
        }
    }
 
    public void test() {
        A a = new A();
        B b = new B(a);
        b.start();
        a.start();
    }
}
public static void main(String[] args) {
    JoinClass example = new JoinClass();
    example.test();
}
           

輸出結果是

A

B

雖然是B線程先執行的,但因為在B線程中調用了a.join(),是以B線程會等待A線程執行完畢才會繼續執行。

wait() notify() notifyAll()

它們都屬于 Object 的方法,而不屬于 Thread。

當調用wait()方法時,線程會被挂起,等待條件滿足,當其他線程調用notify()(随機喚醒一個線程)、 notifyAll()(喚醒所有線程)時來喚醒被挂起的線程。

注意隻能用在同步方法或者同步控制塊中使用!否則會在運作時抛出 IllegalMonitorStateExeception。

**調用wait()方法時,線程會釋放鎖,這樣其他線程才能進入對象的同步代碼中調用對象的notify()方法喚醒線程。**如果沒有釋放鎖,将無法進入對象同步塊中調用notify() notifyAll()方法,造成死鎖。

public class WaitNotifyExample {
    public synchronized void before() {
        System.out.println("before");
        notifyAll();
    }
 
    public synchronized void after() {
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("after");
    }
}
public static void main(String[] args) {
    ExecutorService executorService = Executors.newCachedThreadPool();
    WaitNotifyExample example = new WaitNotifyExample();
    executorService.execute(() -> example.after());
    executorService.execute(() -> example.before());
}
           

執行結果是

before

after

await() signal() signalAll()

**java.util.concurrent 類庫中提供了 Condition 類來實作線程之間的協調,可以在 Condition 上調用 await() 方法使線程等待,其它線程調用 signal() 或 signalAll() 方法喚醒等待的線程。**相比于 wait() 這種等待方式,await() 可以指定等待的條件,是以更加靈活。

sleep和wait有什麼差別

  • sleep() 是Thread類的靜态方法,wait()是Object類的方法。
  • sleep() 不會釋放鎖(抱着鎖睡覺),休眠時間結束後自動恢複(回到就緒狀态)
  • wait()會釋放鎖,當被notify() 方法(或 notifyAll() 方法)喚醒,如果線程重新獲得對象的鎖就可以進入就緒狀态。

原文:https://blog.csdn.net/Zhang_hongxin/article/details/82462267

繼續閱讀