首页 > 代码库 > 架构师养成记--5.线程之间的通信

架构师养成记--5.线程之间的通信

用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 }
View Code

有一个死循环,这种方式很不好。

 

应该用以下方式替代(用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 }
View Code

运行结果:

 技术分享

 

t2先执行,获得lock锁,发现size != 5就释放lock锁。t1线程启动,当size等于5的时候唤醒另一个线程t2,但是不释放lock锁。

 

如果让t1先执行的话执行结果就不通了。因为t1拿到了锁以后就不会释放,等t1十次循环后才释放锁,这时size已经是10 了,t2执行已经晚了。

 

但是使用wait的话有一个问题,不实时,上面也提到了,必须要等一个线程执行完了另一线程才收到通知。

 

应该用上面没注释掉的代码CountDownLatch代替。可以理解成notify和wait的升级版

最终运行结果:

 

技术分享

 

架构师养成记--5.线程之间的通信