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

  接口:public interface Condition

  Condition 将 Object 监视器方法(wait、notify和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 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使用案例之一:实现两个线程交替执行

 import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class ConditionTest { public static void main(String[] args) {
ExecutorService service = Executors.newSingleThreadExecutor();
final Business2 business = new Business2();
service.execute(new Runnable() {//提交5个business.sub方法任务到单个线程池中
public void run() {
for (int i = 0; i < 5; i++) {
business.sub();
}
} }); for (int i = 0; i < 5; i++) {//执行5次business.main方法
business.main();
}
} } class Business2 {
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();//得到当前锁阻塞条件
boolean isSub = true; //默认一开始限制性sub任务 public void sub() {
lock.lock();
if (!isSub) {//不是sub执行条件,则进入进行阻塞处理
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
}
isSub = false;
condition.signal();
} finally {
lock.unlock();
} } public void main() {
lock.lock();
if (isSub) { //是sub执行任务,则进入阻塞main任务
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
}
isSub = true;
condition.signal();
} finally {
lock.unlock();
}
}
}

运行结果如下:

  

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

 import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class SignalTest2 {
public static void main(String[] args) {
new SignalTest2().init();
} private void init() {
final Business b = new Business();
new Thread() {
public void run() {
for (int i = 0; i < 5; i++)
b.sub1();
}
}.start(); new Thread() {
public void run() {
for (int i = 0; i < 5; i++)
b.sub2();
}
}.start(); new Thread() {
public void run() {
for (int i = 0; i < 5; i++)
b.sub3();
}
}.start();
} private class Business {
int status = 1;//开始默认执行第一个方法
Lock lock = new ReentrantLock();
Condition cond1 = lock.newCondition();
Condition cond2 = lock.newCondition();
Condition cond3 = lock.newCondition(); public void sub1() {
lock.lock();
while (status != 1) {
try {
cond1.await();
} catch (Exception e) {
}
}
for (int i = 1; i <= 5; i++) {
try {
Thread.sleep(200);
} catch (Exception e) {}
System.out.println("[sub1]" + Thread.currentThread().getName() + ":" + i);
}
status = 2;//1执行完指定2开始执行
cond2.signal();
lock.unlock();
} public void sub2() {
lock.lock();
while (status != 2) {
try {
cond2.await();
} catch (Exception e) {
}
}
for (int i = 1; i <= 5; i++) {
try {
Thread.sleep(200);
} catch (Exception e) {}
System.out.println("[sub2]" + Thread.currentThread().getName() + ":" + i);
}
status = 3;//2执行完指定3开始执行
cond3.signal();
lock.unlock();
} public void sub3() {
lock.lock();
while (status != 3) {
try {
cond3.await();
} catch (Exception e) {
}
}
for (int i = 1; i <= 5; i++) {
try {
Thread.sleep(200);
} catch (Exception e) {
}
System.out.println("[sub3]" + Thread.currentThread().getName() + ":" + i);
}
status = 1;//3执行完指定1开始执行
cond1.signal();
lock.unlock();
}
}
}

运行结果如下:

  

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

并发库应用之六 & 有条件阻塞Condition应用的更多相关文章

  1. 条件阻塞Condition的应用

    Condition的功能类似在传统线程技术中的Object.wait和Object.notity的功能.   例子:生产者与消费者 import java.util.Random; import ja ...

  2. 并发库应用之五 & ReadWriteLock场景应用

    Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. 读写锁:分为读 ...

  3. 03.Java多线程并发库API使用2

    1.多个线程之间共享数据的方式探讨 1.如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,买票系统就可以这么做. 2.如果每个线程执行的代 ...

  4. 线程高级应用-心得5-java5线程并发库中Lock和Condition实现线程同步通讯

    1.Lock相关知识介绍 好比我同时种了几块地的麦子,然后就等待收割.收割时,则是哪块先熟了,先收割哪块. 下面举一个面试题的例子来引出Lock缓存读写锁的案例,一个load()和get()方法返回值 ...

  5. 并发库应用之十一 & 阻塞队列的应用

    队列包含固定长度的队列和不固定长度的队列,队列的规则就是:先进先出.固定长度的队列往里放数据,如果放满了还要放,阻塞式队列就会等待,直到有数据取出,空出位置后才继续放:非阻塞式队列不能等待就只能报错了 ...

  6. Java线程新特征——Java并发库

    一.线程池   Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定 ...

  7. java并发库 Lock 公平锁和非公平锁

    jdk1.5并发包中ReentrantLock的创建可以指定构造函数的boolean类型来得到公平锁或非公平锁,关于两者区别,java并发编程实践里面有解释 公平锁:   Threads acquir ...

  8. Java多线程同步集合--并发库高级应用

    一.阻塞队列1.在多线程领域,所谓阻塞,在某些情况下会挂起线程,一旦条件满足,被挂起的线程又会自动被唤醒2.ArrayBlockingQueue(效率高)和LinkedBlockingQueue是两个 ...

  9. Java并发(十八):阻塞队列BlockingQueue

    阻塞队列(BlockingQueue)是一个支持两个附加操作的队列. 这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用. 阻塞队列常用于生产 ...

随机推荐

  1. 更新Cocos2D支持Xcode 7

    原文链接(有节选简写) Apple已经释放出Xcode7,给我们带来了Swift2和每个平台的最新版本支持.Cocos2D却还在等待更新去兼容Apple的改变.不幸的是,SpriteBuilder还未 ...

  2. Java进阶(二十二)使用FileOutputStream写入文件

    Java使用FileOutputStream写入文件 绪 在Java中,文件输出流是一种用于处理原始二进制数据的字节流类.为了将数据写入到文件中,必须将数据转换为字节,并保存到文件.请参阅下面的完整的 ...

  3. window环境下搭建react native及相关插件

    可以先浏览一下中文翻译的开发文档具体了解一下关于React Native,想要查看官方文档可以点http://facebook.github.io/react-native/docs/getting- ...

  4. JSP判断移动设备

    日期: 2014年3月6日 人员::铁锚 看到了一篇很好的文章, <在天猫,前端做什么?>,里面有天猫php判断移动设备的正则(个人猜测),觉得很好用,于是就决定移植到JSP里面. jsp ...

  5. 对FMDB的封装JRDB

    在自己开发中,每次用到数据库都会纠结是使用CoreData还是FMDB.CoreData虽然Api简单,但是调用栈非常复杂,要初始化一个Context需要至少20行代码.显然,对于这种这么恶心的情况, ...

  6. nodejs安装及故障解决

    本文来自:http://hxl2009.blog.51cto.com/779549/1031320 给开发搞nodejs环境,遇到点问题记录下过程,备忘. wget http://nodejs.org ...

  7. rhel6.4 安装nodejs和Mysql DB服务

    rhel6.4 安装nodejs和Mysql DB服务 安装好redhat6.4虚拟机后, 安装软件: # yum install gcc-c++ openssl-devel Loaded plugi ...

  8. win32 线程通信初步

    // 线程通信机制.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #define NUM_THREADS 10 #include < ...

  9. 【Android 应用开发】AndroidUI设计之 布局管理器 - 详细解析布局实现

    写完博客的总结 : 以前没有弄清楚的概念清晰化 父容器与本容器属性 : android_layout...属性是本容器的属性, 定义在这个布局管理器的LayoutParams内部类中, 每个布局管理器 ...

  10. linux下用gtk+写比赛赌博GUI小游戏

    游戏界面全部由gtk的GUI完成,没有使用openGL之类的高端货. 游戏玩法就是8位选手比赛跑步,你可以在赛前赌哪位选手会赢,如果输了cash会被扣除,反之cash会增加. 无聊写了3个选项:小数时 ...