并发库应用之六 & 有条件阻塞Condition应用

     Condition的功能类似在传统线程技术中的 Object.wait() 和 Object.natify() 的功能,传统线程技术实现的互斥只能一个线程单独干,不能说这个线程干完了通知另一个线程来干,Condition就是解决这个问题的,实现线程间的通信。比如CPU让小弟做事,小弟说我先歇着先让大哥做并通知大哥,大哥就开始做事。

  接口:public interface Condition

  Condition 将 Object 监视器方法(waitnotifynotifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。

  Condition 实例实质上被绑定到一个锁上。要为特定 Lock 实例获得 Condition 实例,请使用其 newCondition() 方法。

  作为一个示例,假定有一个绑定的缓冲区,它支持 put 和 take 方法。如果试图在空的缓冲区上执行 take 操作,则在某一个项变得可用之前,线程将一直阻塞;如果试图在满的缓冲区上执行 put 操作,则在有空间变得可用之前,线程将一直阻塞。我们喜欢在单独的等待 set 中保存 put 线程和 take 线程,这样就可以在缓冲区中的项或空间变得可用时利用,一次只通知一个线程。可以使用两个 Condition 实例来做到这一点。

  一个锁内部可以有多个Condition,即有多路等待和通知,可以参看jdk1.5提供的 Lock 与 Condition 实现的可阻塞队列的应用案例,从中除了要体味算法,还要体味面向对象的封装。

Condition使用案例之一:实现两个线程交替执行

 1 import java.util.concurrent.ExecutorService;
 2 import java.util.concurrent.Executors;
 3 import java.util.concurrent.locks.Condition;
 4 import java.util.concurrent.locks.Lock;
 5 import java.util.concurrent.locks.ReentrantLock;
 6 
 7 public class ConditionTest {
 8 
 9     public static void main(String[] args) {
10         ExecutorService service = Executors.newSingleThreadExecutor();
11         final Business2 business = new Business2();
12         service.execute(new Runnable() {//提交5个business.sub方法任务到单个线程池中
13             public void run() {
14                 for (int i = 0; i < 5; i++) {
15                     business.sub();
16                 }
17             }
18 
19         });
20 
21         for (int i = 0; i < 5; i++) {//执行5次business.main方法
22             business.main();
23         }
24     }
25 
26 }
27 
28 class Business2 {
29     Lock lock = new ReentrantLock();
30     Condition condition = lock.newCondition();//得到当前锁阻塞条件
31     boolean isSub = true; //默认一开始限制性sub任务
32 
33     public void sub() {
34         lock.lock();
35         if (!isSub) {//不是sub执行条件,则进入进行阻塞处理
36             try {
37                 condition.await();
38             } catch (InterruptedException e) {
39                 e.printStackTrace();
40             }
41         }
42         try {
43             for (int i = 0; i < 5; i++) {
44                 System.out.println(Thread.currentThread().getName() + " : " + i);
45             }
46             isSub = false;
47             condition.signal();
48         } finally {
49             lock.unlock();
50         }
51 
52     }
53 
54     public void main() {
55         lock.lock();
56         if (isSub) { //是sub执行任务,则进入阻塞main任务
57             try {
58                 condition.await();
59             } catch (InterruptedException e) {
60                 e.printStackTrace();
61             }
62         }
63         try {
64             for (int i = 0; i < 5; i++) {
65                 System.out.println(Thread.currentThread().getName() + " : " + i);
66             }
67             isSub = true;
68             condition.signal();
69         } finally {
70             lock.unlock();
71         }
72     }
73 }

运行结果如下:

  

Condition使用案例之:实现三个线程交替执行

 1 import java.util.concurrent.locks.Condition;
 2 import java.util.concurrent.locks.Lock;
 3 import java.util.concurrent.locks.ReentrantLock;
 4 
 5 public class SignalTest2 {
 6     public static void main(String[] args) {
 7         new SignalTest2().init();
 8     }
 9 
10     private void init() {
11         final Business b = new Business();
12         new Thread() {
13             public void run() {
14                 for (int i = 0; i < 5; i++)
15                     b.sub1();
16             }
17         }.start();
18 
19         new Thread() {
20             public void run() {
21                 for (int i = 0; i < 5; i++)
22                     b.sub2();
23             }
24         }.start();
25 
26         new Thread() {
27             public void run() {
28                 for (int i = 0; i < 5; i++)
29                     b.sub3();
30             }
31         }.start();
32     }
33 
34     private class Business {
35         int status = 1;//开始默认执行第一个方法
36         Lock lock = new ReentrantLock();
37         Condition cond1 = lock.newCondition();
38         Condition cond2 = lock.newCondition();
39         Condition cond3 = lock.newCondition();
40 
41         public void sub1() {
42             lock.lock();
43             while (status != 1) {
44                 try {
45                     cond1.await();
46                 } catch (Exception e) {
47                 }
48             }
49             for (int i = 1; i <= 5; i++) {
50                 try {
51                     Thread.sleep(200);
52                 } catch (Exception e) {}
53                 System.out.println("[sub1]" + Thread.currentThread().getName() + ":" + i);
54             }
55             status = 2;//1执行完指定2开始执行
56             cond2.signal();
57             lock.unlock();
58         }
59 
60         public void sub2() {
61             lock.lock();
62             while (status != 2) {
63                 try {
64                     cond2.await();
65                 } catch (Exception e) {
66                 }
67             }
68             for (int i = 1; i <= 5; i++) {
69                 try {
70                     Thread.sleep(200);
71                 } catch (Exception e) {}
72                 System.out.println("[sub2]" + Thread.currentThread().getName() + ":" + i);
73             }
74             status = 3;//2执行完指定3开始执行
75             cond3.signal();
76             lock.unlock();
77         }
78 
79         public void sub3() {
80             lock.lock();
81             while (status != 3) {
82                 try {
83                     cond3.await();
84                 } catch (Exception e) {
85                 }
86             }
87             for (int i = 1; i <= 5; i++) {
88                 try {
89                     Thread.sleep(200);
90                 } catch (Exception e) {
91                 }
92                 System.out.println("[sub3]" + Thread.currentThread().getName() + ":" + i);
93             }
94             status = 1;//3执行完指定1开始执行
95             cond1.signal();
96             lock.unlock();
97         }
98     }
99 }

运行结果如下:

  

提示:欢迎继续参看我相关的下一篇博客:并发库应用之七 & 信号灯Semaphore应用

 

posted @ 2017-03-08 19:06  星火燎原智勇  阅读(994)  评论(0编辑  收藏