摘要:必須放在中,否則會在時扔出異常。為了控制線程執行的順序,那么就必須要確定喚醒等待的順序,所以每一個線程必須同時持有兩個對象鎖,才能繼續執行。一個對象鎖是,就是前一個線程所持有的對象鎖。
簡單介紹
wait()方法是Object類里的方法;當一個線程執行到wait()方法時,它就進入到一個和該對象相關的等待池中,同時失去(釋放)了對象的機鎖(暫時失去機鎖,wait(long timeout)超時時間到后還需要返還對象鎖);其他線程可以訪問;wait()使用notify或者notifyAlll或者指定睡眠時間來喚醒當前等待池中的線程。wiat()必須放在synchronized block中,否則會在program runtime時扔 出“java.lang.IllegalMonitorStateException”異常。 簡單的介紹就到這里,現在我們用一個例子來深入理解一下
package com.example.demo.test.MultithreadingTest; public class MyThreadPrinter2 implements Runnable { private String name; private Object prev; private Object self; private MyThreadPrinter2(String name, Object prev, Object self) { this.name = name; this.prev = prev; this.self = self; } @Override public void run() { int count = 10; int x=0; while (count > 0) { synchronized (prev) { synchronized (self) { System.out.print(name); count--; x++; self.notify(); } try { prev.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized (prev){ System.out.print(x); } } } public static void main(String[] args) throws Exception { Object a = new Object(); Object b = new Object(); Object c = new Object(); MyThreadPrinter2 pa = new MyThreadPrinter2("A", c, a); MyThreadPrinter2 pb = new MyThreadPrinter2("B", a, b); MyThreadPrinter2 pc = new MyThreadPrinter2("C", b, c); new Thread(pa).start(); Thread.sleep(100); new Thread(pb).start(); Thread.sleep(100); new Thread(pc).start(); Thread.sleep(100); } }
輸出結果:
ABC1A1B1C2A2B2C3A3B3C4A4B4C5A5B5C6A6B6C7A7B7C8A8B8C9A9B9C10
這段代碼為三線程間的同步喚醒操作,主要的目的就是ThreadA->ThreadB->ThreadC->ThreadA循環執行三個線程。
為了控制線程執行的順序,那么就必須要確定喚醒、等待的順序,所以每一個線程必須同時持有兩個對象鎖,才能繼續執行。一個對象鎖是prev,就是前一個線程所持有的對象鎖。還有一個就是自身對象鎖。主要的思想就是,為了控制執行的順序,必須要先持有prev鎖,也就前一個線程要釋放自身對象鎖,再去申請自身對象鎖,兩者兼備時打印,之后首先調用self.notify()釋放自身對象鎖,喚醒下一個等待線程,再調用prev.wait()釋放prev對象鎖,終止當前線程,等待循環結束后再次被喚醒。prev.wait()之后,加入了一個對象鎖是prev的輸出x,用來展示什么時候釋放了prev對象鎖。
運行上述代碼,可以發現先打印出A,再釋放A,然后C鎖,進入ThreadB,打印出B,再釋放B,然后A鎖,進入ThreadC,打印出C,再釋放C,然后B鎖,此時會進入ThreadA,繼續執行開始時wait的線程,輸出x,打印出A,再釋放A,然后C鎖......如此循環
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71618.html
摘要:和簡介和均為的方法暫停一個線程喚醒一個線程從以上的定義中,我們可以了解到以下事實想要使用這兩個方法,我們需要先有一個對象。在中任何一個時刻,對象的控制權只能被一個線程擁有。若有多個線程處于此控制權下的狀態,只有一個會被喚醒。 最近看帖子,發現一道面試題: 啟動兩個線程, 一個輸出 1,3,5,7…99, 另一個輸出 2,4,6,8…100 最后 STDOUT 中按序輸出 1,2,3,4...
摘要:無論在中出現什么,都可以認為它是對象除了八大基本數據類型。讓當前線程等待某個對象的鎖,當然應該通過這個對象來操作了。但是要注意的是方法調用后,被喚醒的線程不會立馬獲得到鎖對象。主要的區別在于在釋放同時,釋放了對象鎖的控制。 前言 五一回家又斷更了一個放假時間了~~~ 只有光頭才能變強 回顧前面: ThreadLocal就是這么簡單 多線程三分鐘就可以入個門了! 多線程基礎必要知識點!...
摘要:方法可以將當前線程放入等待集合中,并釋放當前線程持有的鎖。此后,該線程不會接收到的調度,并進入休眠狀態。該線程會喚醒,并嘗試恢復之前的狀態。 并發 最近重新復習了一邊并發的知識,發現自己之前對于并發的了解只是皮毛。這里總結以下Java并發需要掌握的點。 使用并發的一個重要原因是提高執行效率。由于I/O等情況阻塞,單個任務并不能充分利用CPU時間。所以在單處理器的機器上也應該使用并發。為...
摘要:運行可運行狀態的線程獲得了時間片,執行程序代碼。阻塞的情況分三種一等待阻塞運行的線程執行方法,會把該線程放入等待隊列中。死亡線程方法執行結束,或者因異常退出了方法,則該線程結束生命周期。死亡的線程不可再次復生。 系列文章傳送門: Java多線程學習(一)Java多線程入門 Java多線程學習(二)synchronized關鍵字(1) java多線程學習(二)synchronized關鍵...
閱讀 2897·2021-11-15 11:39
閱讀 1520·2021-08-19 10:56
閱讀 1097·2019-08-30 14:12
閱讀 3740·2019-08-29 17:29
閱讀 723·2019-08-29 16:21
閱讀 3424·2019-08-26 12:22
閱讀 1519·2019-08-23 16:30
閱讀 1024·2019-08-23 15:25