JavaSE——線程通訊,javase線程
線程通訊:
如果線程A和線程B持有同一個MyObject類的對象object,這兩個線程會去調用不同的方法,但是它們是同步執行的,比如:線程B需要等待線程A執行完了methodA()方法之後,它才能執行methodB()方法。這樣,線程A和線程B就實現了 通訊。
線程通訊中要用到的方法:wait()方法:
執行同步鎖(obj對象)的該方法的線程進入堵塞狀態,會釋放對象的鎖,java虛擬機器把該線程放到該對象的等待池中,該線程如果要再次執行,則需要其他線程將它喚醒。
1 package tongxin; 2 3 public class MyThreadA extends Thread { 4 private Object obj; 5 public MyThreadA(String name,Object obj){ 6 7 super(name); 8 this.obj = obj; 9 10 }11 public void run(){12 synchronized(obj){ //設定obj為同步鎖13 14 for(int i = 0;i<10;i++){15 System.out.println(Thread.currentThread().getName()+"---"+i);16 17 if(i == 5){18 try {19 obj.wait();20 } catch (InterruptedException e) {21 // TODO Auto-generated catch block22 e.printStackTrace();23 }24 try {25 sleep(100);26 } catch (InterruptedException e) {27 // TODO Auto-generated catch block28 e.printStackTrace();29 }30 }31 }32 }33 }34 35 }
1 package tongxin; 2 3 public class Demo01 { 4 5 public static void main(String[] args) { 6 // TODO Auto-generated method stub 7 8 Object obj = new Object(); 9 MyThreadA mt1 = new MyThreadA("A",obj);10 mt1.start();11 12 }13 14 }
output:
1 A---02 A---13 A---24 A---35 A---46 A---5
當i = 5時,執行了同步鎖的wait()方法,然後線程A將同步鎖釋放進入堵塞狀態,如果A線程還有恢複運行,則需要另一個持相同同步鎖的線程將其喚醒。
喚醒線程的方法:notifi()
另一個線程在運行過程中執行了同步鎖的notifi方法, 會喚醒在對象的等待池中等待的一個線程(隨機播放),java虛擬機器會隨機播放一個線程轉到對象的鎖池中。
注意一個線程要去喚醒另一個執行了wait()方法進入堵塞狀態的線程,則其要去執行同一個同步鎖的notifi()方法。
假如有一個房間,A進去之後把門鎖上,A在房間裡睡著了,B要把A叫醒,就要用鎖(同步鎖)上的鑰匙把門開開。A與B用的是同一把鎖,只不過A是在鎖門(wait()方法),B是在開門(notifi()方法)。
1 package tongxin; 2 3 public class MyThreadB extends Thread { 4 private Object obj; 5 public MyThreadB(String name,Object obj){ 6 7 super(name); 8 this.obj = obj; 9 10 }11 public void run(){12 synchronized(obj){ //設定obj為同步鎖13 14 for(int i = 0;i<10;i++){15 System.out.println(Thread.currentThread().getName()+"---"+i);16 17 if(i == 2){18 obj.notify();19 try {20 sleep(100);21 } catch (InterruptedException e) {22 // TODO Auto-generated catch block23 e.printStackTrace();24 }25 }26 }27 }28 }29 30 31 }
1 package tongxin; 2 3 public class Demo01 { 4 5 public static void main(String[] args) { 6 // TODO Auto-generated method stub 7 8 Object obj = new Object(); 9 MyThreadA mt1 = new MyThreadA("A",obj);10 MyThreadB mt2 = new MyThreadB("B",obj);11 mt1.start();12 mt2.start();13 14 15 }16 17 }
output:
A---0A---1A---2A---3A---4A---5B---0B---1B---2B---3B---4B---5B---6B---7B---8B---9A---6A---7A---8A---9
建立一個新的線程對象B來喚醒A線程,運行過程中,i = 2時,B喚醒A線程將其轉到對象的鎖池中,但此時由於B持有同步鎖所以B線程繼續運行,運行結束後釋放同步鎖,此時A擷取到同步鎖恢複運行。
notifyAll()方法:
該方法會喚醒在這個對象鎖池中的所有線程。
如有不對之處還望指正,謝謝。