并发库应用之六 & 有条件阻塞Condition应用
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应用的更多相关文章
- 条件阻塞Condition的应用
Condition的功能类似在传统线程技术中的Object.wait和Object.notity的功能. 例子:生产者与消费者 import java.util.Random; import ja ...
- 并发库应用之五 & ReadWriteLock场景应用
Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. 读写锁:分为读 ...
- 03.Java多线程并发库API使用2
1.多个线程之间共享数据的方式探讨 1.如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,买票系统就可以这么做. 2.如果每个线程执行的代 ...
- 线程高级应用-心得5-java5线程并发库中Lock和Condition实现线程同步通讯
1.Lock相关知识介绍 好比我同时种了几块地的麦子,然后就等待收割.收割时,则是哪块先熟了,先收割哪块. 下面举一个面试题的例子来引出Lock缓存读写锁的案例,一个load()和get()方法返回值 ...
- 并发库应用之十一 & 阻塞队列的应用
队列包含固定长度的队列和不固定长度的队列,队列的规则就是:先进先出.固定长度的队列往里放数据,如果放满了还要放,阻塞式队列就会等待,直到有数据取出,空出位置后才继续放:非阻塞式队列不能等待就只能报错了 ...
- Java线程新特征——Java并发库
一.线程池 Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定 ...
- java并发库 Lock 公平锁和非公平锁
jdk1.5并发包中ReentrantLock的创建可以指定构造函数的boolean类型来得到公平锁或非公平锁,关于两者区别,java并发编程实践里面有解释 公平锁: Threads acquir ...
- Java多线程同步集合--并发库高级应用
一.阻塞队列1.在多线程领域,所谓阻塞,在某些情况下会挂起线程,一旦条件满足,被挂起的线程又会自动被唤醒2.ArrayBlockingQueue(效率高)和LinkedBlockingQueue是两个 ...
- Java并发(十八):阻塞队列BlockingQueue
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列. 这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用. 阻塞队列常用于生产 ...
随机推荐
- Useful Articles for the Oracle E-Business Suite Technology Stack for Technical Consultant / DBA [ID
Applies to: Oracle Applications Technology Stack - Version: 11.5.10.2 to 12.1.3 - Release: 11.5.10 ...
- 【公开课】【阿里在线技术峰会】魏鹏:基于Java容器的多应用部署技术实践
对于公开课,可能目前用不上这些,但是往往能在以后想解决方案的时候帮助到我.以下是阿里对公开课的整理 摘要: 在首届阿里巴巴在线峰会上,阿里巴巴中间件技术部专家魏鹏为大家带来了题为<基于Java容 ...
- iOS关于蓝牙连接的简单介绍与使用
下面是两台iPhone6连接同一台蓝牙设备的结果: **成功连接**** peripheral: <CBPeripheral: 0x1700f4500, identifier = 50084F6 ...
- jQuery:多个AJAX/JSON请求对应单个回调
原文链接:jQuery: Multiple AJAX and JSON Requests, One Callback 原文日期: 2014年4月15日 翻译日期: 2014年4月22日 翻译人员: 铁 ...
- C语言之选择排序
选择法排序是相对好理解的排序算法.假设要对含有n个数的序列进行升序排列,算法步骤是: 1.从数组存放的n个数中找出最小数的下标(算法见下面的"求最值"),然后将最小数与第1个数交换 ...
- LeetCode之“动态规划”:Valid Parentheses && Longest Valid Parentheses
1. Valid Parentheses 题目链接 题目要求: Given a string containing just the characters '(', ')', '{', '}', '[ ...
- Linux - 停机常用的anacron
什么是 anacron anacron 并不是用来取代 crontab 的,anacron 存在的目的就在於我们上头提到的,在处理非 24 小时一直启动的 Linux 系统的 crontab 的运行! ...
- 内核调试神器SystemTap — 更多功能与原理(三)
a linux trace/probe tool. 官网:https://sourceware.org/systemtap/ 用户空间 SystemTap探测用户空间程序需要utrace的支持,3.5 ...
- Linux下进程通信方式(简要概述)
http://blog.sina.com.cn/s/blog_65c209580100u0ee.html (1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先 ...
- Smali语法汇总(一)
Opcode 操作码(hex) Opcode name 操作码名称 Explanation 说明 Example 示例 00 nop 无操作 0000 - nop 01 move vx, vy 移动v ...