多线程:线程之间的协作(join、wait、notify、notifyAll、await、signal、signalAll)
當(dāng)多個(gè)線程可以一起工作去解決某個(gè)問題時(shí),如果某些部分必須在其它部分之前完成,那么就需要對線程進(jìn)行協(xié)調(diào)。
join()
在線程中調(diào)用另一個(gè)線程的 join() 方法,會將當(dāng)前線程掛起,而不是忙等待,直到目標(biāo)線程結(jié)束。
對于以下代碼,雖然 b 線程先啟動,但是因?yàn)樵?b 線程中調(diào)用了 a 線程的 join() 方法,b 線程會等待 a 線程結(jié)束才繼續(xù)執(zhí)行,因此最后能夠保證 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()
調(diào)用 wait() 使得線程等待某個(gè)條件滿足,線程在等待時(shí)會被掛起,當(dāng)其他線程的運(yùn)行使得這個(gè)條件滿足時(shí),其它線程會調(diào)用 notify() 或者 notifyAll() 來喚醒掛起的線程。
它們都屬于 Object 的一部分,而不屬于 Thread。
只能用在同步方法或者同步控制塊中使用,否則會在運(yùn)行時(shí)拋出 IllegalMonitorStateException。
使用 wait() 掛起期間,線程會釋放鎖。這是因?yàn)?#xff0c;如果沒有釋放鎖,那么其它線程就無法進(jìn)入對象的同步方法或者同步控制塊中,那么就無法執(zhí)行 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() 的區(qū)別
- wait() 是 Object 的方法,而 sleep() 是 Thread 的靜態(tài)方法;
- wait() 會釋放鎖,sleep() 不會。
await() signal() signalAll()
java.util.concurrent 類庫中提供了 Condition 類來實(shí)現(xiàn)線程之間的協(xié)調(diào),可以在 Condition 上調(diào)用 await() 方法使線程等待,其它線程調(diào)用 signal() 或 signalAll() 方法喚醒等待的線程。
相比于 wait() 這種等待方式,await() 可以指定等待的條件,因此更加靈活。
使用 Lock 來獲取一個(gè) 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 《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的多线程:线程之间的协作(join、wait、notify、notifyAll、await、signal、signalAll)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多线程:中断(interrupt、int
- 下一篇: 多线程:并发实现方法之J.U.C