JAVA 執行緒通訊相關知識彙總
兩個執行緒之間的通訊
多執行緒環境下CPU會隨機的線上程之間進行切換,如果想讓兩個執行緒有規律的去執行,那就需要兩個執行緒之間進行通訊,在Object類中的兩個方法wait和notify可以實現通訊。
wait方法可以使當前執行緒進入到等待狀態,在沒有被喚醒的情況下,執行緒會一直保持等待狀態。
notify方法可以隨機喚醒單個在等待狀態下的執行緒。
來實現這樣的一個功能:
讓兩個執行緒交替在控制檯輸出一行文字
定義一個Print類,有兩個方法print1和print2,分別列印一行不同的內容
package com.sutaoyu.volatlt; public class Print { private int flag = 1; public void print1() { synchronized(this) { if(flag != 1) { try { //讓當前執行緒進入等入狀態 this.wait(); }catch(InterruptedException e) { e.printStackTrace(); } } System.out.println("monkey"); flag = 2; //隨機的喚醒單個等待的執行緒 this.notify(); } } public void print2() { synchronized(this) { if(flag != 2) { try { this.wait(); }catch (InterruptedException e){ e.printStackTrace(); } } System.out.println("1024"); flag = 1; this.notify(); } } }
定義執行緒測試類,開啟兩個執行緒,分別執行Print類中print1和print2方法
package com.sutaoyu.volatlt; public class NotifyTest01 { public static void main(String[] args) { Print p = new Print(); Thread t1 = new Thread() { public void run() { while(true) { p.print1(); } } }; Thread t2 = new Thread() { public void run() { while(true) { p.print2(); } } }; t1.start(); t2.start(); } }
三個及三個以上的執行緒之間的通訊
改造上面程式碼在Print類中新增一個print3方法,再開啟第三個執行緒來執行這個方法。
另外需要修改的地方是:
1.因為notifyAll方法可以喚醒所有等待狀態的執行緒,所有用notifyAll方法來替代notify方法
2.當執行緒被喚醒後,需要先判斷一下flag的值,if不會重新判斷flag值,而while會重新判斷flag的值,所以將Print中的if判斷修改為while判斷。
package com.sutaoyu.volatlt; public class Print { private int flag = 1; public void print1() { synchronized(this) { while(flag != 1) { try { //讓當前執行緒進入等入狀態 this.wait(); }catch(InterruptedException e) { e.printStackTrace(); } } System.out.println("monkey"); flag = 2; //隨機的喚醒單個等待的執行緒 this.notifyAll(); } } public void print2() { synchronized(this) { while(flag != 2) { try { this.wait(); }catch (InterruptedException e){ e.printStackTrace(); } } System.out.println("1024"); flag = 3; this.notifyAll(); } } public void print3() { synchronized(this) { while(flag != 3) { try { this.wait(); }catch(InterruptedException e) { e.printStackTrace(); } } System.out.println("888"); flag = 1; this.notifyAll(); } } }
package com.sutaoyu.volatlt; public class NotifyTest01 { public static void main(String[] args) { Print p = new Print(); Thread t1 = new Thread() { public void run() { while(true) { p.print1(); } } }; Thread t2 = new Thread() { public void run() { while(true) { p.print2(); } } }; Thread t3 = new Thread() { public void run() { while(true) { p.print3(); } } }; t1.start(); t2.start(); t3.start(); } }
執行緒通訊注意事項
在print1,2,3方法中同步程式碼塊中使用哪個物件作為鎖,那在呼叫wait和notify方法時一定要呼叫這個物件上的wait和notify方法。
上面程式使用this作為物件鎖,在下面呼叫的都是this.wait()和this.notify()方法。
在多執行緒執行當中
wait方法釋放物件鎖,根據上面的程式碼示例,t1,t2,t3三個執行緒使用的是同一個物件鎖,如果wait方法不釋放鎖的話,別的執行緒就不能獲取到該鎖,也就不能獲取cpu的執行權了。
sleep和notify方法不釋放物件鎖,上面程式碼示例中,如果notify方法釋放鎖的話,別的執行緒就有可能獲取到cpu的執行權,這樣子就會導致當前notify方法後面的程式碼還未執行完畢就失去了cpu的執行權,從而導致一些問題,只有當執行緒執行完synchronized程式碼塊後才會釋放鎖。
以上就是JAVA 執行緒通訊相關知識彙總的詳細內容,更多關於JAVA 執行緒通訊的資料請關注我們其它相關文章!