并发库应用之六 & 有条件阻塞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)是一个支持两个附加操作的队列. 这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用. 阻塞队列常用于生产 ...
随机推荐
- 一起来搭简单的App框架
1.概述 最近在学车,抽着空写了一个常用的App框架,可惜不会制作gif图片,请忽略录屏软件的那个浮动窗口,要是有更好的方式制作gif麻烦告知下提前感谢,效果图如下,凑合着看下吧. 主要实现了 [1] ...
- Windows Mobile和Wince(Windows Embedded CE)的字符集问题
背景 开发过Windows Mobile和Wince(Windows Embedded CE)的开发者,特别是Native C++开发者,或多或少都遇到过ANSI字符集和Unicode字符集的转换问题 ...
- Android应用---基于NDK的samples例程hello-jni学习NDK开发
Android应用---基于NDK的samples例程hello-jni学习NDK开发 NDK下载地址:http://developer.android.com/tools/sdk/ndk/index ...
- 《android入门第一季》之android目录结构详解
在搭建Android开发环境及简单地建立一个HelloWorld项目后,本篇将通过HelloWorld项目来介绍Android项目的目录结构.本文的主要主题如下: 1.HelloWorld项目的目录结 ...
- mongodb系列之--mongodb 主从配置与说明
一.为什么要配置mongodb的主从: 1.做主从,可以说是做数据的备份,有利于故障的恢复 2.做主从,可以做到读写分离,主节点负责写操作,从节点负责读操作,这样就把读写压力分开,保证系统的稳定性. ...
- 深度剖析linux内核万能--双向链表,Hash链表模版
我们都知道,链表是数据结构中用得最广泛的一种数据结构,对于数据结构,有顺序存储,数组就是一种.有链式存储,链表算一种.当然还有索引式的,散列式的,各种风格的说法,叫法层出不穷,但是万变不离其中,只要知 ...
- Tomcat configuration DataSource
1. configuration MySql Connection DataSource 原理介绍 java 调用 Tomcat 中的 ConnectionPool 通过Context 中去查找 j ...
- 安卓TV开发(九) Android模拟事件 遥控器变身成鼠标来操作TV
本文出处:http://blog.csdn.net/sk719887916/article/details/40348853,作者:skay 阅读此文建议先阅读 安卓Tv开发(二)移动智能电 ...
- 脚本自动化 ant
用ant,shell下也可以用make. 1,ant 是一个自动化编译工具,安装使用. 2,编写build.xml,核心,写明进行哪些操作,删,建,编译,javac,java等,从例子可以看出每个操作 ...
- C# 视频多人脸识别
上一篇内容的调整,并按 @轮回 的说法,提交到git了,https://github.com/catzhou2002/ArcFaceDemo 基本思路如下: 一.识别线程 1.获取当前图片 2.识别当 ...