多线程:线程之间的协作(join、wait、notify、notifyAll、await、signal、signalAll)
當多個線程可以一起工作去解決某個問題時,如果某些部分必須在其它部分之前完成,那么就需要對線程進行協調。
join()
在線程中調用另一個線程的 join() 方法,會將當前線程掛起,而不是忙等待,直到目標線程結束。
對于以下代碼,雖然 b 線程先啟動,但是因為在 b 線程中調用了 a 線程的 join() 方法,b 線程會等待 a 線程結束才繼續執行,因此最后能夠保證 a 線程的輸出先于 b 線程的輸出。
public class JoinExample {private class A extends Thread {@Overridepublic void run() {System.out.println("A");}}private class B extends Thread {private A a;B(A a) {this.a = a;}@Overridepublic 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) {JoinExample example = new JoinExample();example.test(); } A Bwait() notify() notifyAll()
調用 wait() 使得線程等待某個條件滿足,線程在等待時會被掛起,當其他線程的運行使得這個條件滿足時,其它線程會調用 notify() 或者 notifyAll() 來喚醒掛起的線程。
它們都屬于 Object 的一部分,而不屬于 Thread。
只能用在同步方法或者同步控制塊中使用,否則會在運行時拋出 IllegalMonitorStateException。
使用 wait() 掛起期間,線程會釋放鎖。這是因為,如果沒有釋放鎖,那么其它線程就無法進入對象的同步方法或者同步控制塊中,那么就無法執行 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 afterwait() 和 sleep() 的區別
- wait() 是 Object 的方法,而 sleep() 是 Thread 的靜態方法;
- wait() 會釋放鎖,sleep() 不會。
await() signal() signalAll()
java.util.concurrent 類庫中提供了 Condition 類來實現線程之間的協調,可以在 Condition 上調用 await() 方法使線程等待,其它線程調用 signal() 或 signalAll() 方法喚醒等待的線程。
相比于 wait() 這種等待方式,await() 可以指定等待的條件,因此更加靈活。
使用 Lock 來獲取一個 Condition 對象。
public class AwaitSignalExample {private Lock lock = new ReentrantLock();private Condition condition = lock.newCondition();public void before() {lock.lock();try {System.out.println("before");condition.signalAll();} finally {lock.unlock();}}public void after() {lock.lock();try {condition.await();System.out.println("after");} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}} } public static void main(String[] args) {ExecutorService executorService = Executors.newCachedThreadPool();AwaitSignalExample example = new AwaitSignalExample();executorService.execute(() -> example.after());executorService.execute(() -> example.before()); } before after 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的多线程:线程之间的协作(join、wait、notify、notifyAll、await、signal、signalAll)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多线程:中断(interrupt、int
- 下一篇: 多线程:并发实现方法之J.U.C