并发库应用之六 & 有条件阻塞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)是一个支持两个附加操作的队列. 这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用. 阻塞队列常用于生产 ...
随机推荐
- Cocos2D中的Framerate状态
对于额外绘制调试物理引擎的支持,Cocos2D同样可以绘制概述计数器,尤其是帧速率(framerate)显示. 为了启用这些概述计数器标签,你只需添加如下一行代码,比如说在AppDelegate.m里 ...
- C++语言之动态内存分配
在C语言中,我们熟悉的内存分配与释放的最常用的接口分别是malloc , free .在C++中: 存在着更加方便的动态存储分配: 1.new 和delete 机制,new 它能更可靠控制存储区的分配 ...
- Smali语法汇总(一)
Opcode 操作码(hex) Opcode name 操作码名称 Explanation 说明 Example 示例 00 nop 无操作 0000 - nop 01 move vx, vy 移动v ...
- Unity 实现模拟按键
一直在想,使用模拟按键,也可以实现一些AI操作,具体还没做过,这里使用user32.dll在unity里写的一个简单demo using UnityEngine; using System.Colle ...
- ruby直接字符串压缩与解压缩
ruby2.1.3的核心类中包含了Zlib库,其中的Zlib模块包含了对字符串压缩和解压的方法: irb(main):180:0> Zlib.class => Module irb(mai ...
- 《深入理解Java虚拟机》读书笔记2--垃圾回收
回收哪些内存/对象 引用计数算法 可达性分析算法 finalize()方法 HotSpot实现分析 转载:http://blog.csdn.net/tjiyu/article/details/5398 ...
- iframe之局部刷新
例如: <iframe src="1.htm" name="ifrmname" id="ifrmid"></ifram ...
- C++:LIB和DLL的区别与使用
共有两种库: 一种是LIB包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供,称为动态链接库dynamic link library. 一种是LIB包含 ...
- python---购物车---更新
购物车程序更新: 更新商家入口,实现以下功能: 1. 商家能够修改商品价格: 2. 商家能够下线商品: 3. 商家能够增加商品: 4. 商品信息存在文件中 # -*- coding:utf-8 -*- ...
- ffmpeg转换参数和压缩输出大小的比率 参考 最新版本FFMPEG
https://blog.cnlabs.NET/3668.html ffmpeg 转换压缩比例 FFMPEG如果是压缩为FLV文件 3个编码可选1. -c:v flv 标准FLV编码 这个好处是速度快 ...