摘要:已經(jīng)在上面有提到過,和的作用是喚醒正在的線程,是隨機(jī)喚醒線程中的一個(gè),則是喚醒全部。釋放和不釋放鎖在多線程的操作中,鎖的釋放與否是必須要清楚的,是會(huì)釋放鎖,而則不會(huì)。
wait
wait方法是Object中的方法,這個(gè)方法的功能特性:
1).執(zhí)行wait方法的前提是當(dāng)前線程已經(jīng)獲取到對象的鎖,也就是wait方法必須在synchronized修飾的代碼塊或者方法中使用。
2).執(zhí)行wait之后,會(huì)失去鎖的所有權(quán)
3).wait方法執(zhí)行后會(huì)一直等待,直到被調(diào)用notify()、notifyAll()或者所在線程被中斷。
4).被調(diào)用notify()或者notifyAll()后,線程還是會(huì)等待,直到擁有鎖的所有權(quán),才會(huì)繼續(xù)往下執(zhí)行。
下面舉個(gè)例子:
public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Thread t1 = new Thread(new Test().new Tt1(lock1)); Thread t2 = new Thread(new Test().new Tt2(lock1)); t1.start(); Thread.sleep(1000); t2.start(); } class Tt1 implements Runnable{ private Object lock1; public Tt1(Object lock1) { this.lock1 = lock1; } @Override public void run() { try { System.out.println(this.getClass()+"-------1"); synchronized (lock1) { Thread.sleep(2000); System.out.println("waiting start"); lock1.wait(); } System.out.println("waiting end"); } catch (InterruptedException e) { e.printStackTrace(); } } } class Tt2 implements Runnable{ private Object lock1; public Tt2(Object lock1) { this.lock1 = lock1; } @Override public void run() { System.out.println(this.getClass()+"-------1"); synchronized (lock1) { try { System.out.println(this.getClass()+"-------2"); lock1.notify(); Thread.sleep(1000); System.out.println(this.getClass()+"-------3"); } catch (Exception e) { e.printStackTrace(); } } } }
執(zhí)行結(jié)果:
class Test$Tt1-------1 class Test$Tt2-------1 waiting start class Test$Tt2-------2 class Test$Tt2-------3 waiting end
分析一下:
第1、2行:t1和t2啟動(dòng),t1先獲取到鎖所以t2一直被阻塞住
第3、4行:t1中執(zhí)行了wait,鎖被釋放,所以t2繼續(xù)執(zhí)行下去。
第5、6行:t2中調(diào)用了notify()但是t1沒有馬上執(zhí)行,因?yàn)殒i現(xiàn)在是被t2擁有,等t2執(zhí)行完成釋放鎖后,t1繼續(xù)執(zhí)行。
notify已經(jīng)在上面有提到過,notify和notifyAll 的作用是喚醒正在wait的線程,notify是隨機(jī)喚醒wait線程中的一個(gè),notifyAll 則是喚醒全部。
1).執(zhí)行notify、notifyAll 方法的前提是當(dāng)前線程已經(jīng)獲取到對象的鎖,也就是必須在synchronized修飾的代碼塊或者方法中使用。這個(gè)和wait是一樣的。
2).被調(diào)用notify()或者notifyAll()后,線程還是會(huì)等待,直到擁有鎖的所有權(quán),才會(huì)繼續(xù)往下執(zhí)行。
3)notify、notifyAll不會(huì)釋放鎖,這個(gè)與wait不同。
在多線程的操作中,鎖的釋放與否是必須要清楚的,wait是會(huì)釋放鎖,而notify(notifyAll)則不會(huì)。先舉個(gè)wait的例子:
public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Thread t1 = new Thread(new Test().new Tt1(lock1)); Thread t2 = new Thread(new Test().new Tt2(lock1)); t1.start(); Thread.sleep(100); t2.start(); } class Tt1 implements Runnable{ private Object lock1; public Tt1(Object lock1) { this.lock1 = lock1; } @Override public void run() { try { synchronized (lock1) { System.out.println(Thread.currentThread().getName()+"---start"); lock1.wait(); Thread.sleep(3000); System.out.println(Thread.currentThread().getName()+"---end"); } } catch (InterruptedException e) { e.printStackTrace(); } } } class Tt2 implements Runnable{ private Object lock1; public Tt2(Object lock1) { this.lock1 = lock1; } @Override public void run() { synchronized (lock1) { try { System.out.println(Thread.currentThread().getName()+"---start"); System.out.println(Thread.currentThread().getName()+"---end"); } catch (Exception e) { e.printStackTrace(); } } } }
執(zhí)行結(jié)果:
Thread-0---start Thread-1---start Thread-1---end
Thread-0執(zhí)行wait后馬上釋放了鎖,所以Thread-1很快接著就執(zhí)行。
再來notify的例子,其實(shí)就是把上一個(gè)例子wait()改成nofity():
public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Thread t1 = new Thread(new Test().new Tt1(lock1)); Thread t2 = new Thread(new Test().new Tt2(lock1)); t1.start(); Thread.sleep(100); t2.start(); } class Tt1 implements Runnable{ private Object lock1; public Tt1(Object lock1) { this.lock1 = lock1; } @Override public void run() { try { synchronized (lock1) { System.out.println(Thread.currentThread().getName()+"---start"); lock1.notify(); Thread.sleep(3000); System.out.println(Thread.currentThread().getName()+"---end"); } } catch (InterruptedException e) { e.printStackTrace(); } } } class Tt2 implements Runnable{ private Object lock1; public Tt2(Object lock1) { this.lock1 = lock1; } @Override public void run() { synchronized (lock1) { try { System.out.println(Thread.currentThread().getName()+"---start"); System.out.println(Thread.currentThread().getName()+"---end"); } catch (Exception e) { e.printStackTrace(); } } } }
執(zhí)行結(jié)果:
Thread-0---start Thread-0---end Thread-1---start Thread-1---end
可見Thread-0在執(zhí)行nofity后并沒有釋放鎖,而是等待代碼塊執(zhí)行完之后才釋放鎖,Thread-1才能繼續(xù)執(zhí)行。
必須先獲取鎖無論是notify還是wait都是要先獲取鎖,既必須在synchronized內(nèi)使用,舉個(gè)反例:
public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Thread t1 = new Thread(new Test().new Tt1(lock1)); t1.run(); } class Tt1 implements Runnable{ private Object lock1; public Tt1(Object lock1) { this.lock1 = lock1; } @Override public void run() { try { lock1.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } }
執(zhí)行結(jié)果:
Exception in thread "main" java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at Test$Tt1.run(Test.java:24) at java.lang.Thread.run(Thread.java:748) at Test.main(Test.java:11)wait()遇到interrupt()
之前說道interrupt(),并不會(huì)直接中斷線程,而是會(huì)給線程一個(gè)中斷標(biāo)志,而且包括sleep、wait、join會(huì)拋出InterruptedException。
public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Thread t1 = new Thread(new Test().new Tt1(lock1)); t1.start(); Thread.sleep(100); t1.interrupt(); } class Tt1 implements Runnable{ private Object lock1; public Tt1(Object lock1) { this.lock1 = lock1; } @Override public void run() { synchronized (lock1) { try { System.out.println(Thread.currentThread().getName()+"---start"); lock1.wait(); System.out.println(Thread.currentThread().getName()+"---end"); }catch (InterruptedException e) { System.out.println("線程被中斷了");; } catch (Exception e) { e.printStackTrace(); } } } }
執(zhí)行結(jié)果:
Thread-0---start 線程被中斷了notifyAll和nofity
notifyAll和nofity唯一的不同就是,可以喚醒全部和喚醒一個(gè), 先舉個(gè)nofity的例子
public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Thread t1 = new Thread(new Test().new Tt1(lock1)); Thread t2 = new Thread(new Test().new Tt1(lock1)); Thread t3 = new Thread(new Test().new Tt2(lock1)); t1.start(); Thread.sleep(100); t2.start(); Thread.sleep(100); t3.start(); } class Tt1 implements Runnable{ private Object lock1; public Tt1(Object lock1) { this.lock1 = lock1; } @Override public void run() { synchronized (lock1) { try { System.out.println(Thread.currentThread().getName()+"---start"); System.out.println(Thread.currentThread().getName()+"---wait"); lock1.wait(); System.out.println(Thread.currentThread().getName()+"---end"); } catch (Exception e) { e.printStackTrace(); } } } } class Tt2 implements Runnable{ private Object lock1; public Tt2(Object lock1) { this.lock1 = lock1; } @Override public void run() { synchronized (lock1) { try { System.out.println(Thread.currentThread().getName()+"---start"); System.out.println(Thread.currentThread().getName()+"---notify"); lock1.notify(); System.out.println(Thread.currentThread().getName()+"---end"); } catch (Exception e) { e.printStackTrace(); } } } }
執(zhí)行結(jié)果:
Thread-0---start Thread-0---wait Thread-1---start Thread-1---wait Thread-2---start Thread-2---notify Thread-2---end Thread-0---end
Thread-0和Thread-1在wait,Thread-2執(zhí)行了notify,但只有Thread-0被喚醒,重新開始執(zhí)行,Thread-1還在wait。
再來看看nofityAll:
public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Thread t1 = new Thread(new Test().new Tt1(lock1)); Thread t2 = new Thread(new Test().new Tt1(lock1)); Thread t3 = new Thread(new Test().new Tt2(lock1)); t1.start(); Thread.sleep(100); t2.start(); Thread.sleep(100); t3.start(); } class Tt1 implements Runnable{ private Object lock1; public Tt1(Object lock1) { this.lock1 = lock1; } @Override public void run() { synchronized (lock1) { try { System.out.println(Thread.currentThread().getName()+"---start"); System.out.println(Thread.currentThread().getName()+"---wait"); lock1.wait(); System.out.println(Thread.currentThread().getName()+"---end"); } catch (Exception e) { e.printStackTrace(); } } } } class Tt2 implements Runnable{ private Object lock1; public Tt2(Object lock1) { this.lock1 = lock1; } @Override public void run() { synchronized (lock1) { try { System.out.println(Thread.currentThread().getName()+"---start"); System.out.println(Thread.currentThread().getName()+"---notifyAll"); lock1.notifyAll(); System.out.println(Thread.currentThread().getName()+"---end"); } catch (Exception e) { e.printStackTrace(); } } } }
執(zhí)行結(jié)果:
Thread-0---start Thread-0---wait Thread-1---start Thread-1---wait Thread-2---start Thread-2---notifyAll Thread-2---end Thread-1---end Thread-0---end
Thread-2執(zhí)行了notifyAll后,Thread-1和Thread-0都被喚醒。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/76374.html
摘要:和簡介和均為的方法暫停一個(gè)線程喚醒一個(gè)線程從以上的定義中,我們可以了解到以下事實(shí)想要使用這兩個(gè)方法,我們需要先有一個(gè)對象。在中任何一個(gè)時(shí)刻,對象的控制權(quán)只能被一個(gè)線程擁有。若有多個(gè)線程處于此控制權(quán)下的狀態(tài),只有一個(gè)會(huì)被喚醒。 最近看帖子,發(fā)現(xiàn)一道面試題: 啟動(dòng)兩個(gè)線程, 一個(gè)輸出 1,3,5,7…99, 另一個(gè)輸出 2,4,6,8…100 最后 STDOUT 中按序輸出 1,2,3,4...
摘要:線程通信的目標(biāo)是使線程間能夠互相發(fā)送信號(hào)。但是,這個(gè)標(biāo)志已經(jīng)被第一個(gè)喚醒的線程清除了,所以其余醒來的線程將回到等待狀態(tài),直到下次信號(hào)到來。如果方法調(diào)用,而非,所有等待線程都會(huì)被喚醒并依次檢查信號(hào)值。 線程通信的目標(biāo)是使線程間能夠互相發(fā)送信號(hào)。另一方面,線程通信使線程能夠等待其他線程的信號(hào)。 showImg(http://segmentfault.com/img/bVbPLD); 例...
摘要:運(yùn)行可運(yùn)行狀態(tài)的線程獲得了時(shí)間片,執(zhí)行程序代碼。阻塞的情況分三種一等待阻塞運(yùn)行的線程執(zhí)行方法,會(huì)把該線程放入等待隊(duì)列中。死亡線程方法執(zhí)行結(jié)束,或者因異常退出了方法,則該線程結(jié)束生命周期。死亡的線程不可再次復(fù)生。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1) java多線程學(xué)習(xí)(二)synchronized關(guān)鍵...
摘要:典型地,和被用在等待另一個(gè)線程產(chǎn)生的結(jié)果的情形測試發(fā)現(xiàn)結(jié)果還沒有產(chǎn)生后,讓線程阻塞,另一個(gè)線程產(chǎn)生了結(jié)果后,調(diào)用使其恢復(fù)。使當(dāng)前線程放棄當(dāng)前已經(jīng)分得的時(shí)間,但不使當(dāng)前線程阻塞,即線程仍處于可執(zhí)行狀態(tài),隨時(shí)可能再次分得時(shí)間。 1、說說進(jìn)程,線程,協(xié)程之間的區(qū)別 簡而言之,進(jìn)程是程序運(yùn)行和資源分配的基本單位,一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程.進(jìn)程在執(zhí)行過程中擁有獨(dú)立的內(nèi)存單元...
摘要:通知任一一個(gè)進(jìn)入等待狀態(tài)的線程,通知所有讓調(diào)用線程阻塞在這個(gè)方法上,直到的線程完全執(zhí)行完畢,調(diào)用線程才會(huì)繼續(xù)執(zhí)行。通知調(diào)度器,主動(dòng)讓出對的占用。 多線程在開發(fā)知識(shí)中是一個(gè)很重要的部分,然而實(shí)際生產(chǎn)中卻很少遇到真正需要自己去處理多線程編程里的那些復(fù)雜細(xì)節(jié)和問題,因?yàn)楹芏鄷r(shí)候,都有一套架構(gòu)或者一些框架幫大部分業(yè)務(wù)程序員隱藏了多線程的細(xì)節(jié),大多時(shí)候只需要簡單的實(shí)現(xiàn)各種業(yè)務(wù)邏輯即可。 今天來理...
閱讀 1956·2021-11-23 09:51
閱讀 1255·2019-08-30 15:55
閱讀 1626·2019-08-30 15:44
閱讀 774·2019-08-30 14:11
閱讀 1154·2019-08-30 14:10
閱讀 924·2019-08-30 13:52
閱讀 2642·2019-08-30 12:50
閱讀 626·2019-08-29 15:04