环境(Condition)因素对对象的等待和通知方法(waite(),notify()和notifyall()方法)作为不同的状态对象,给这些对象的多个等待集合的影响。这里我们用锁(Lock)取代同步(synchronize)方法和阻塞,环境(Condition)取代对象的等待(wait)和唤醒(notifycation)的方法。

Note 环境(Condition)实例本质上是包含一个锁(lock)。为了包含一个环境(Condition)实例给一个锁实例,我们运用锁(Lock)的newCondition()方法。

环境(Condition)声明了下面的方法:

  • void await(): 强迫请求的线程处于等待状态直到它需要签名或打断。
  • boolean await(long time, TimeUnit unit): 强迫请求的线程处于等待状态直到它需要签名或打断,或直到指定等待的时间范围内。
  • long awaitNanos(long nanosTimeout): 强迫请求的线程处于等待状态直到它需要签名或打断,或直到指定等待的时间范围内。
  • void awaitUniterruptibly():强迫请求的线程处于等待状态直到它需要签名。
  • boolean awaitUnit(Date deadline): 强迫请求的线程处于等待状态直到它需要签名或打断,或直到指定截止时间。
  • void signal():唤醒一个等待的线程。
  • void signalAll():唤醒所有等待的线程。

下面的例子使用环境(Condition)的方法实例生产者与消费者的应用。

package com.owen.thread.chapter7;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class PC
{public static void main(String[] args){Shared s = new Shared();new Producer(s).start();new Consumer(s).start();}
}class Shared
{private char c;private volatile boolean available;private final Lock lock;private final Condition condition;Shared(){available = false;lock = new ReentrantLock();condition = lock.newCondition();}Lock getLock(){return lock;}char getSharedChar(){lock.lock();try{while (!available)try{condition.await();}catch (InterruptedException ie){ie.printStackTrace();}available = false;condition.signal();} finally{lock.unlock();return c;}}void setSharedChar(char c){lock.lock();try{while (available)try{condition.await();} catch (InterruptedException ie){ie.printStackTrace();}this.c = c;available = true;condition.signal();} finally{lock.unlock();}}
}class Producer extends Thread
{private final Lock l;private final Shared s;Producer(Shared s){this.s = s;l = s.getLock();}@Overridepublic void run(){for (char ch = 'A'; ch <= 'Z'; ch++){l.lock();s.setSharedChar(ch);System.out.println(ch + " produced by producer.");l.unlock();}}
}class Consumer extends Thread
{private final Lock l;private final Shared s;Consumer(Shared s){this.s = s;l = s.getLock();}@Overridepublic void run(){char ch;do{l.lock();ch = s.getSharedChar();System.out.println(ch + " consumed by consumer.");l.unlock();} while (ch != 'Z');}}

上面的代码PCmain()方法实例Shared、Producer和Consumer的类。而Shared是通过Producer和Consumer实例化的。

Producer和Consumer的构造者是在主线中被调用的。因为Share的实例化需要在Producer和Consumer的线程中,这个实例必须出现这些有效的线程中(尤其这些线程运行在不同的核中)。通过声明s使最终完成任务。在这个域中我们声明了一个volatile的变量,为了确保s在被初始化后不会更改。

观察Share的构造器,你会察觉到,它创建了一个锁为lock = new ReentrantLock(),和一个环境(Condition),通过锁来创建的condition = lock.newCondition()。这个锁通过getLock()的方法获取有效的producer和consumer.

producer线程执行Share的void setSharedChar(char c)的方法去产生一个字符和写出一条信息。这个方法锁定先前那个锁对象,并且进入一个while的循环重复测试是否可用,如果生产的字母可用于消费那么就会返回true.

当available为true时,生产者就会去执行环境(condition)的await()方法去等待available变为fale。当消费者需要消费字母时,消费者发出信号给环境(condition)去唤醒生产者。(我运用一个循环去替代if语句,因为虚假唤醒是可能的和available可能总是为true.)

之后离开循环,生产者的线程会记录新的字母,availble为true表明一个字母可以给消费者,并且通知环境去唤醒一个等待的生产者。最后,释放锁和执行setShareChar()。

Note 在Producer的run()方法中,我们锁住了setSharedChar()和System.out.println();在Consumer的run()方法中,我们锁了getSharedChar()和System.out.println()。生产信息之前需要消费信息;消费信息之前需要生产信息。

在消费者的行为线程和getSharedChar()方法,类似于我们仅仅描述的生产者和setSharedChar()的方法。

Note 我并没有使用try/finally的语句去确保锁在生产和消费中无效,因为我们不希望在上下文中抛出异常。

执行上面的代码,你可能等到如下的结果:

A produced by producer.
A consumed by consumer.
B produced by producer.
B consumed by consumer.
C produced by producer.
C consumed by consumer.
D produced by producer.
D consumed by consumer.
••••

7.3 环境(Condition)相关推荐

  1. Lock锁的简单使用

    Lock锁与synchronize关键字的区别: 1.Lock锁可以在我们需要的地方显式的调用,或者中断,以及超时获取锁等更加灵活的锁操作;但是失去了synchronize隐式获取与释放的便捷性. 2 ...

  2. 已知环境静态障碍物避障_我女儿如何教我无障碍环境

    已知环境静态障碍物避障 by Drew 通过德鲁 我女儿如何教我无障碍环境 (How my daughter taught me about accessibility) 在过去的几个月里,花了很多时 ...

  3. 分布式环境下,互斥性与幂等性问题,分析与解决思路

    欢迎关注方志朋的博客,回复"666"获面试宝典 随着互联网信息技术的飞速发展,数据量不断增大,业务逻辑也日趋复杂,对系统的高并发访问.海量数据处理的场景也越来越多.如何用较低成本实 ...

  4. Python标准库threading模块Condition原理浅析

    Python标准库threading模块Condition原理浅析 本文环境python3.5.2 threading模块Condition的实现思路 在Python的多线程实现过程中,在Linux平 ...

  5. 正式环境docker部署hyperf_应用部署 - Docker Swarm 集群搭建 - 《Hyperf v1.1.1 开发文档》 - 书栈网 · BookStack...

    Docker Swarm 集群搭建 现阶段,Docker容器技术已经相当成熟,就算是中小型公司也可以基于 Gitlab.Aliyun镜像服务.Docker Swarm 轻松搭建自己的 Docker集群 ...

  6. build怎么调试 react_GitHub - bozhouyongqi/debug-react: 本地调试react源码环境

    [TOC] 工欲善其事,必先利其器. 在学习raect源码时,如果能够在浏览器中单步调试,势必会加深理解.其实可以借助webpack的resolve.alias将react等指向本地的目录,这样就不会 ...

  7. bean ref的bean可以做判断吗_Spring Boot @Condition 注解,组合条件你知道吗

    写在前面 当我们构建一个 Spring 应用的时候,有时我们想在满足指定条件的时候才将某个 bean 加载到应用上下文中, 在Spring 4.0 时代,我们可以通过 @Conditional 注解来 ...

  8. 24 UsageEnvironment使用环境抽象基类——Live555源码阅读(三)UsageEnvironment

    24 UsageEnvironment使用环境抽象基类--Live555源码阅读(三)UsageEnvironment 24 UsageEnvironment使用环境抽象基类--Live555源码阅读 ...

  9. Linux环境下段错误的产生原因及调试方法小结

    From:http://www.cnblogs.com/panfeng412/archive/2011/11/06/2237857.html 最近在Linux环境下做C语言项目,由于是在一个原有项目基 ...

  10. 『中级篇』Minikube快速搭建K8S单节点环境(61)

    原创文章,欢迎转载.转载请注明:转载自IT人故事会,谢谢! 原文链接地址:『中级篇』Minikube快速搭建K8S单节点环境(61) 去介绍k8s的集群安装,本地搭建一个k8s的集群. 不会科学上网的 ...

最新文章

  1. 现代化 Web 应用开发实战
  2. JIRA中vm后缀文件语法说明
  3. 单例模式示例_单例设计模式示例
  4. 软件开发管理(产品经理客户和程序员互撕解决方案)
  5. ajax实时刷新处理
  6. 华为机试HJ8:合并表记录
  7. ubuntu下NS2+leach算法安装笔记(1)
  8. Linux驱动——编译驱动的两种形式(内核目录外、内核目录中)
  9. ESP32文件系统esp_littlefs实例
  10. 第二十五课:文件的读写
  11. dedecms模板配置大概流程
  12. Learning to Rank系列之Pointwise方法
  13. 深入iOS系统底层之静态库介绍
  14. echarts r 地图_用R与Stata绘制地图,让文稿shinly起来
  15. 影响乔布斯的13个人和9本书
  16. QuickFIX 源码分析
  17. argc,**argv
  18. probuf 流无协议文件反序列化
  19. nrf52832 学习笔记(七)蓝牙协议层级理解
  20. openssl_private_encrypt(): key param is not a valid private key

热门文章

  1. 【网络流24题】No.4 魔术球问题 (二分+最小路径覆盖)
  2. MySQL数据库INSERT、UPDATE、DELETE以及REPLACE语句的用法详解
  3. busybox的编译和使用
  4. [cocos2dx笔记015]关于cocos2dx Button三种状态说明
  5. LeetCode: Implement strStr() [027]
  6. Servlet连接数据库
  7. memcached 远程拒绝服务漏洞
  8. [转载]一个本科生在世界五大顶尖咨询公司实习心得
  9. Silverlight实用窍门系列:51.Silverlight页面控件的放大缩小、Silverlight和Html控件的互相操作【附带源码实例】...
  10. 基于Cocos2d-x开发guardCarrot--3 《保卫萝卜2》主页面开发(仅使用Cocos2d-x)