• 并发库应用之六 & 有条件阻塞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应用

  • 相关阅读:
    ASP.NET MVC 部分视图
    IIS7.5安全配置研究
    微信公众号抢现金红包活动的核心代码分析(asp.net C#)
    [Android] hid设备按键流程简述
    [Android] AudioTrack::start
    [Android] createTrack_l
    [Android] 输入系统(三):加载按键映射
    [Android] 获取音频输出getOutput
    [Android] AudioTrack实例
    [Android] 输入系统(二)
  • 原文地址:https://www.cnblogs.com/liang1101/p/6522375.html
Copyright © 2020-2023  润新知