标签:升级版 run 升级 停止 exception port img div war
用wait和notify来实现线程之间的通信,这两个方法是object方法,这两个方法必须要配合synchronized使用。wait方法释放锁,notify不释放锁。
原始线程通信方式
1 import java.util.ArrayList; 2 import java.util.List; 3 4 public class ListAdd1 { 5 6 7 private volatile static List list = new ArrayList(); 8 9 public void add(){ 10 list.add("bjsxt"); 11 } 12 public int size(){ 13 return list.size(); 14 } 15 16 public static void main(String[] args) { 17 18 final ListAdd1 list1 = new ListAdd1(); 19 20 Thread t1 = new Thread(new Runnable() { 21 @Override 22 public void run() { 23 try { 24 for(int i = 0; i <10; i++){ 25 list1.add(); 26 System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素.."); 27 Thread.sleep(500); 28 } 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 } 33 }, "t1"); 34 35 Thread t2 = new Thread(new Runnable() { 36 @Override 37 public void run() { 38 while(true){ 39 if(list1.size() == 5){ 40 System.out.println("当前线程收到通知:" + Thread.currentThread().getName() + " list size = 5 线程停止.."); 41 throw new RuntimeException(); 42 } 43 } 44 } 45 }, "t2"); 46 47 t1.start(); 48 t2.start(); 49 } 50 51 52 }
有一个死循环,这种方式很不好。
应该用以下方式替代(用wait),注意线程启动顺序:
1 import java.util.ArrayList; 2 import java.util.List; 3 import java.util.Queue; 4 import java.util.concurrent.CountDownLatch; 5 import java.util.concurrent.LinkedBlockingDeque; 6 import java.util.concurrent.LinkedBlockingQueue; 7 /** 8 * wait notfiy 方法,wait释放锁,notfiy不释放锁 9 * @author alienware 10 * 11 */ 12 public class ListAdd2 { 13 private volatile static List list = new ArrayList(); 14 15 public void add(){ 16 list.add("bjsxt"); 17 } 18 public int size(){ 19 return list.size(); 20 } 21 22 public static void main(String[] args) { 23 24 final ListAdd2 list2 = new ListAdd2(); 25 26 // 1 实例化出来一个 lock 27 // 当使用wait 和 notify 的时候 , 一定要配合着synchronized关键字去使用 28 //final Object lock = new Object(); 29 30 final CountDownLatch countDownLatch = new CountDownLatch(1); 31 32 Thread t1 = new Thread(new Runnable() { 33 @Override 34 public void run() { 35 try { 36 //synchronized (lock) { 37 for(int i = 0; i <10; i++){ 38 list2.add(); 39 System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素.."); 40 Thread.sleep(500); 41 if(list2.size() == 5){ 42 System.out.println("已经发出通知.."); 43 countDownLatch.countDown(); 44 //lock.notify(); 45 } 46 } 47 //} 48 } catch (InterruptedException e) { 49 e.printStackTrace(); 50 } 51 52 } 53 }, "t1"); 54 55 Thread t2 = new Thread(new Runnable() { 56 @Override 57 public void run() { 58 //synchronized (lock) { 59 if(list2.size() != 5){ 60 try { 61 //System.out.println("t2进入..."); 62 //lock.wait(); 63 countDownLatch.await(); 64 } catch (InterruptedException e) { 65 e.printStackTrace(); 66 } 67 } 68 System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止.."); 69 throw new RuntimeException(); 70 //} 71 } 72 }, "t2"); 73 74 t2.start(); 75 t1.start(); 76 77 } 78 79 }
运行结果:
t2先执行,获得lock锁,发现size != 5就释放lock锁。t1线程启动,当size等于5的时候唤醒另一个线程t2,但是不释放lock锁。
如果让t1先执行的话执行结果就不通了。因为t1拿到了锁以后就不会释放,等t1十次循环后才释放锁,这时size已经是10 了,t2执行已经晚了。
但是使用wait的话有一个问题,不实时,上面也提到了,必须要等一个线程执行完了另一线程才收到通知。
应该用上面没注释掉的代码CountDownLatch代替。可以理解成notify和wait的升级版
最终运行结果:
标签:升级版 run 升级 停止 exception port img div war
原文地址:http://www.cnblogs.com/sigm/p/6136009.html