线程通信:
如果线程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 block 22 e.printStackTrace(); 23 } 24 try { 25 sleep(100); 26 } catch (InterruptedException e) { 27 // TODO Auto-generated catch block 28 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---0 2 A---1 3 A---2 4 A---3 5 A---4 6 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 block 23 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---0 A---1 A---2 A---3 A---4 A---5 B---0 B---1 B---2 B---3 B---4 B---5 B---6 B---7 B---8 B---9 A---6 A---7 A---8 A---9
创建一个新的线程对象B来唤醒A线程,运行过程中,i = 2时,B唤醒A线程将其转到对象的锁池中,但此时由于B持有同步锁所以B线程继续运行,运行结束后释放同步锁,此时A获取到同步锁恢复运行。
notifyAll()方法:
该方法会唤醒在这个对象锁池中的所有线程。
如有不对之处还望指正,谢谢。