摘要:已經在上面有提到過,和的作用是喚醒正在的線程,是隨機喚醒線程中的一個,則是喚醒全部。釋放和不釋放鎖在多線程的操作中,鎖的釋放與否是必須要清楚的,是會釋放鎖,而則不會。
wait
wait方法是Object中的方法,這個方法的功能特性:
1).執行wait方法的前提是當前線程已經獲取到對象的鎖,也就是wait方法必須在synchronized修飾的代碼塊或者方法中使用。
2).執行wait之后,會失去鎖的所有權
3).wait方法執行后會一直等待,直到被調用notify()、notifyAll()或者所在線程被中斷。
4).被調用notify()或者notifyAll()后,線程還是會等待,直到擁有鎖的所有權,才會繼續往下執行。
下面舉個例子:
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(); } } } }
執行結果:
class Test$Tt1-------1 class Test$Tt2-------1 waiting start class Test$Tt2-------2 class Test$Tt2-------3 waiting end
分析一下:
第1、2行:t1和t2啟動,t1先獲取到鎖所以t2一直被阻塞住
第3、4行:t1中執行了wait,鎖被釋放,所以t2繼續執行下去。
第5、6行:t2中調用了notify()但是t1沒有馬上執行,因為鎖現在是被t2擁有,等t2執行完成釋放鎖后,t1繼續執行。
notify已經在上面有提到過,notify和notifyAll 的作用是喚醒正在wait的線程,notify是隨機喚醒wait線程中的一個,notifyAll 則是喚醒全部。
1).執行notify、notifyAll 方法的前提是當前線程已經獲取到對象的鎖,也就是必須在synchronized修飾的代碼塊或者方法中使用。這個和wait是一樣的。
2).被調用notify()或者notifyAll()后,線程還是會等待,直到擁有鎖的所有權,才會繼續往下執行。
3)notify、notifyAll不會釋放鎖,這個與wait不同。
在多線程的操作中,鎖的釋放與否是必須要清楚的,wait是會釋放鎖,而notify(notifyAll)則不會。先舉個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(); } } } }
執行結果:
Thread-0---start Thread-1---start Thread-1---end
Thread-0執行wait后馬上釋放了鎖,所以Thread-1很快接著就執行。
再來notify的例子,其實就是把上一個例子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(); } } } }
執行結果:
Thread-0---start Thread-0---end Thread-1---start Thread-1---end
可見Thread-0在執行nofity后并沒有釋放鎖,而是等待代碼塊執行完之后才釋放鎖,Thread-1才能繼續執行。
必須先獲取鎖無論是notify還是wait都是要先獲取鎖,既必須在synchronized內使用,舉個反例:
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(); } } }
執行結果:
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(),并不會直接中斷線程,而是會給線程一個中斷標志,而且包括sleep、wait、join會拋出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(); } } } }
執行結果:
Thread-0---start 線程被中斷了notifyAll和nofity
notifyAll和nofity唯一的不同就是,可以喚醒全部和喚醒一個, 先舉個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(); } } } }
執行結果:
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執行了notify,但只有Thread-0被喚醒,重新開始執行,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(); } } } }
執行結果:
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執行了notifyAll后,Thread-1和Thread-0都被喚醒。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76374.html
摘要:和簡介和均為的方法暫停一個線程喚醒一個線程從以上的定義中,我們可以了解到以下事實想要使用這兩個方法,我們需要先有一個對象。在中任何一個時刻,對象的控制權只能被一個線程擁有。若有多個線程處于此控制權下的狀態,只有一個會被喚醒。 最近看帖子,發現一道面試題: 啟動兩個線程, 一個輸出 1,3,5,7…99, 另一個輸出 2,4,6,8…100 最后 STDOUT 中按序輸出 1,2,3,4...
摘要:線程通信的目標是使線程間能夠互相發送信號。但是,這個標志已經被第一個喚醒的線程清除了,所以其余醒來的線程將回到等待狀態,直到下次信號到來。如果方法調用,而非,所有等待線程都會被喚醒并依次檢查信號值。 線程通信的目標是使線程間能夠互相發送信號。另一方面,線程通信使線程能夠等待其他線程的信號。 showImg(http://segmentfault.com/img/bVbPLD); 例...
摘要:運行可運行狀態的線程獲得了時間片,執行程序代碼。阻塞的情況分三種一等待阻塞運行的線程執行方法,會把該線程放入等待隊列中。死亡線程方法執行結束,或者因異常退出了方法,則該線程結束生命周期。死亡的線程不可再次復生。 系列文章傳送門: Java多線程學習(一)Java多線程入門 Java多線程學習(二)synchronized關鍵字(1) java多線程學習(二)synchronized關鍵...
摘要:典型地,和被用在等待另一個線程產生的結果的情形測試發現結果還沒有產生后,讓線程阻塞,另一個線程產生了結果后,調用使其恢復。使當前線程放棄當前已經分得的時間,但不使當前線程阻塞,即線程仍處于可執行狀態,隨時可能再次分得時間。 1、說說進程,線程,協程之間的區別 簡而言之,進程是程序運行和資源分配的基本單位,一個程序至少有一個進程,一個進程至少有一個線程.進程在執行過程中擁有獨立的內存單元...
摘要:通知任一一個進入等待狀態的線程,通知所有讓調用線程阻塞在這個方法上,直到的線程完全執行完畢,調用線程才會繼續執行。通知調度器,主動讓出對的占用。 多線程在開發知識中是一個很重要的部分,然而實際生產中卻很少遇到真正需要自己去處理多線程編程里的那些復雜細節和問題,因為很多時候,都有一套架構或者一些框架幫大部分業務程序員隱藏了多線程的細節,大多時候只需要簡單的實現各種業務邏輯即可。 今天來理...
閱讀 1917·2021-11-23 09:51
閱讀 1246·2019-08-30 15:55
閱讀 1613·2019-08-30 15:44
閱讀 759·2019-08-30 14:11
閱讀 1146·2019-08-30 14:10
閱讀 915·2019-08-30 13:52
閱讀 2630·2019-08-30 12:50
閱讀 615·2019-08-29 15:04