java线程之线程通信控制

在上篇我们看到,A线程往公共资源库(对象)提供了一条数据,然后B线程从库中提取了数据并打印出来。

实际项目中,我们不可能只往库中提供一条数据,而且库的大小也不会是无穷大的,那么我们就会有这样一

个需求:A线程提供了一定的数据量后就暂停,等待B线程全部取走之后(因为B再不来取的话,库就装不下

了),A线程再往其中添加数据,如此往复。这里存在两种方法;

1.资源库对象的wait()方法和notify()方法/notifyAll()方法

 1 public class Share {
 2     String name;
 3     String sex;
 4     //用empty来表示库中是否有数据
 5     boolean empty = true;
 6 
 7     // 线程A的任务,提供数据
 8     synchronized public void product(String name, String sex) {
 9         try {
10             while(!empty) {
11                 //当库中数据不为空时,A线程不能向其添加数据,小憩一会儿
12                 this.wait();
13             }
14             //当库中数据为空时,A线程向其添加数据
15             this.name = name;
16             this.sex = sex;
17             //添加完成之后,更改库中数据状态为不空,并唤醒其他线程来拿数据
18             empty=false;
19             this.notifyAll();
20         } catch (InterruptedException e) {
21             e.printStackTrace();
22         }
23 
24     }
25 
26     // 线程B的任务,提取(显示)数据
27     synchronized public void show() {
28         try {
29             while(empty) {
30                 //当库中数据为空时,B线程不能获取数据,小憩一会儿
31                 this.wait();
32             }
33             //当库中数据不为空时,B线程获取数据并打印
34             System.out.println("姓名:" + this.name + "性别:" + this.sex);
35             //拿完数据之后,更改库中数据状态为空,并唤醒其他线程继续写数据
36             empty=true;
37             this.notifyAll();
38         } catch (InterruptedException e) {
39             e.printStackTrace();
40         }
41     }
42 }

wait()方法和notifyAll()方法只能由同步监听器对象来调用,就是这里说的资源库对象。

2.同步锁(Lock)和Condition接口

之前讲线程同步时有说到同步锁的方法,这种方法是没有同步监听器对象的,那么上面的wait()等方法就不能用了,

但是不用担心,java5在推出同步锁的时候也为其通信控制提供了一个方法获得Condition对象,来实现通信控制

 1 public class Share {
 2     String name;
 3     String sex;
 4     //创建锁
 5     final Lock lock = new ReentrantLock();
 6     //创建Condition对象
 7     Condition condition = lock.newCondition();
 8     // 用empty来表示库中是否有数据
 9     boolean empty = true;
10 
11     // 线程A的任务,提供数据
12     public void product(String name, String sex) {
13         lock.lock();//上锁
14         try {
15             while (!empty) {
16                 // 当库中数据不为空时,A线程不能向其添加数据,小憩一会儿
17                 condition.await();
18             }
19             // 当库中数据为空时,A线程向其添加数据
20             this.name = name;
21             this.sex = sex;
22             // 添加完成之后,更改库中数据状态为不空,并唤醒其他线程来拿数据
23             empty = false;
24             condition.signalAll();
25         } catch (InterruptedException e) {
26             e.printStackTrace();
27         }
28         lock.unlock();//解锁
29     }
30 
31     // 线程B的任务,提取(显示)数据
32      public void show() {
33          lock.lock();//上锁
34         try {
35             while (empty) {
36                 // 当库中数据为空时,B线程不能获取数据,小憩一会儿
37                 condition.await();
38             }
39             // 当库中数据不为空时,B线程获取数据并打印
40             System.out.println("姓名:" + this.name + "性别:" + this.sex);
41             // 拿完数据之后,更改库中数据状态为空,并唤醒其他线程继续写数据
42             empty = true;
43             condition.signalAll();
44         } catch (InterruptedException e) {
45             e.printStackTrace();
46         }
47         condition.signalAll();//解锁
48     }
49 }
原文地址:https://www.cnblogs.com/eco-just/p/7772348.html