并发库应用之六 & 有条件阻塞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)是一个支持两个附加操作的队列. 这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用. 阻塞队列常用于生产 ...
随机推荐
- 《java入门第一季》之StringBuffer小案例
这里是针对其反转功能来举的例子,再对比之前写的一篇String类的反转功能,StringBuffer明显提高了代码量,提高了效率. import java.util.Scanner; /* * 把字符 ...
- C语言中sizeof与strlen区别
本文转载自:http://www.2cto.com/kf/201109/105100.html 1. 以字符串形式出现的,编译器都会为该字符串自动添加一个0作为结束符,如在代码中写"abc& ...
- hibernate关联对象的增删改查------增
本文可作为,北京尚学堂马士兵hibernate课程的学习笔记. 这一节,我们看看hibernate关联关系的增删改查 就关联关系而已,咱们在上一节已经提了很多了,一对多,多对一,单向,双向... 其实 ...
- 如何写好一个UITableView(完整版)
本文是直播分享的简单文字整理,直播共分为上.下两部分.第一部分:优酷 Or YouTube,第二部分:优酷 Demo 地址:KtTableView 如果你觉得UITableViewDelegate和U ...
- 未能加载文件或程序集“file:///C:\Program Files (x86)\SAP BusinessObjects\Crystal Reports for .NET Framework 4.0
未能加载文件或程序集"file:///C:\Program Files (x86)\SAP BusinessObjects\Crystal Reports for .NET Framewor ...
- Hbase节点管理
1.退役节点 (1) shell>balance_switch false 然后,hbase-daemon.sh stop regionserver (2) graceful_stop.sh U ...
- 用shell脚本挂载linux主机拷贝相应文件copy.sh
#!/bin/sh # $1 MOUNTDIR $2 TARGETDIR $3 ERRORLOG #参数检查 if test $# -ne 3 then echo "argument che ...
- Java反编译工具(Java Decompiler)
Java Decompiler是一种非常实用的JAVA反编译工具,可以对整个jar包进行反编译,也可以将其集成到eclipse上,非常方便的根据class文件的源码.,官网地址http://jd.be ...
- 14.QT-QFile文件,QBuffer缓冲区,QDir目录,QFileSystemWatcher文件系统监视
QFile Qt中所有与IO相关的类都继承于QIODevice,继承图如下所示: 其中QFile类便是用于文件操作的类 在QT中,将文件当做一种特殊的外部设备对待(比如:串口,usb等就是外部设备) ...
- css3-------:before和:after的作用
1.:before和:after的作用就是在指定的元素内容(而不是元素本身)之前或者之后插入一个包含content属性指定内容的行内元素,最基本的用法如下: <!doctype html> ...