ConditionObject 监视器方法(waitnotifynotifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。

先看一个关于Condition使用的简单实例:

 public class ConditionTest {
public static void main(String[] args) {
final Lock lock = new ReentrantLock();
final Condition condition = lock.newCondition(); Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
lock.lock();
System.out.println("我需要等一个信号"+this);
condition.await();
System.out.println("我拿到一个信号"+this);
} catch (Exception e) {
// TODO: handle exception
} finally{
lock.unlock();
} }
}, "thread1");
thread1.start();
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
lock.lock();
System.out.println("我拿到了锁");
Thread.sleep(500);
System.out.println("我发出一个信号");
condition.signal();
} catch (Exception e) {
// TODO: handle exception
} finally{
lock.unlock();
} }
}, "thread2");
thread2.start();
}
}

运行结果:

 我需要等一个信号com.luchao.traditionalthread.ConditionTest$1@10bc3c9
我拿到了锁
我发出一个信号
我拿到一个信号com.luchao.traditionalthread.ConditionTest$1@10bc3c9

可以看到,Condition的执行方式,是当在线程1中调用await方法后,线程1将释放锁,并且将自己沉睡,等待唤醒,线程2获取到锁后,开始做事,完毕后,调用Condition的signal方法,唤醒线程1,线程1恢复执行。

以上说明Condition是一个多线程间协调通信的工具类,使得某个,或者某些线程一起等待某个条件(Condition),只有当该条件具备( signal 或者 signalAll方法被带调用)时 ,这些等待线程才会被唤醒,从而重新争夺锁。

Condition与传统线程通信有些类似,它的使用更广,可以将多个线程进行通信,以完成更加复杂的通信。

用Condition替换传统线程通信,在前面的传统有一个子线程和主线程交替运行50次的实例,使用Condition也可以完成。

代码如下:

 public class ConditionCommuniction {
public static void main(String[] args) {
final Business business = new Business();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
business.sub(i);
}
}
}).start();
for (int i = 0; i < 50; i++) {
business.main(i);
}
} static class Business{
private Lock lock = new ReentrantLock();
private boolean isMain = true;
private Condition condition = lock.newCondition();
public void main(int i){
lock.lock();
try {
while(!isMain){
condition.await();
}
for (int j = 0; j < 100; j++) {
System.out.println("main is looping :" + j +" in " + i);
}
isMain = false;
condition.signal();
} catch (Exception e) {
// TODO: handle exception
} finally{
lock.unlock();
}
}
public void sub(int i){
lock.lock();
try {
while(isMain){
condition.await();
}
for (int j = 0; j < 10; j++) {
System.out.println("sub is looping :" + j +" in " + i);
}
isMain = true;
condition.signal();
} catch (Exception e) {
// TODO: handle exception
} finally{
lock.unlock();
}
}
}
}

  在Condition中,用await()替换wait(),用signal()替换notify(),用signalAll()替换notifyAll(),传统线程的通信方式,Condition都可以实现,这里注意,Condition是被绑定到Lock上的,要创建一个Lock的Condition必须用newCondition()方法。

  这样看来,Condition和传统的线程通信没什么区别,Condition的强大之处在于它可以为多个线程间建立不同的Condition,下面引入API中的一段代码,加以说明。

 class BoundedBuffer {
final Lock lock = new ReentrantLock();//锁对象
final Condition notFull = lock.newCondition();//写线程条件
final Condition notEmpty = lock.newCondition();//读线程条件 final Object[] items = new Object[100];//缓存队列
int putptr/*写索引*/, takeptr/*读索引*/, count/*队列中存在的数据个数*/; public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)//如果队列满了
notFull.await();//阻塞写线程
items[putptr] = x;//赋值
if (++putptr == items.length) putptr = 0;//如果写索引写到队列的最后一个位置了,那么置为0
++count;//个数++
notEmpty.signal();//唤醒读线程
} finally {
lock.unlock();
}
} public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)//如果队列为空
notEmpty.await();//阻塞读线程
Object x = items[takeptr];//取值
if (++takeptr == items.length) takeptr = 0;//如果读索引读到队列的最后一个位置了,那么置为0
--count;//个数--
notFull.signal();//唤醒写线程
return x;
} finally {
lock.unlock();
}
}
}

  这就是多个Condition的强大之处,假设缓存队列中已经存满,那么阻塞的肯定是写线程,唤醒的肯定是读线程,相反,阻塞的肯定是读线程,唤醒的肯定是写线程,那么假设只有一个Condition会有什么效果呢,缓存队列中已经存满,这个Lock不知道唤醒的是读线程还是写线程了,如果唤醒的是读线程,皆大欢喜,如果唤醒的是写线程,那么线程刚被唤醒,又被阻塞了,这时又去唤醒,这样就浪费了很多时间。

  将上面主线程和子线程交替运行的程序进行扩展,三个线程交替运行,代码如下:

 public class ThreeConditionCommunication {
public static void main(String[] args) {
final Business business = new Business();
new Thread(new Runnable() { @Override
public void run() {
for (int i = 0; i < 50; i++) {
business.sub1(i);
}
}
}).start();
new Thread(new Runnable() { @Override
public void run() {
for (int i = 0; i < 50; i++) {
business.sub2(i);
}
}
}).start();
for (int i = 0; i < 50; i++) {
business.main(i);
}
}
static class Business{
Lock lock = new ReentrantLock();
Condition main = lock.newCondition();
Condition sub1 = lock.newCondition();
Condition sub2 = lock.newCondition();
int runNum = 1; public void main(int i){
lock.lock();
try {
while(runNum!=1){
main.await();//主线程等待
}
for (int j = 0; j < 100; j++) {
System.out.println("main is looping of "+j+" in "+i);
}
runNum = 2;
sub1.signal();//唤醒子线程1
} catch (Exception e) {
// TODO: handle exception
} finally{
lock.unlock();
}
}
public void sub1(int i){
lock.lock();
try {
while(runNum!=2){
sub1.await();//子线程1等待
}
for (int j = 0; j < 10; j++) {
System.out.println("sub1 is looping of "+j+" in "+i);
}
runNum = 3;
sub2.signal();//唤醒子线程2
} catch (Exception e) {
// TODO: handle exception
} finally{
lock.unlock();
}
}
public void sub2(int i){
lock.lock();
try {
while(runNum!=3){
sub2.await();//子线程2等待
}
for (int j = 0; j < 20; j++) {
System.out.println("sub2 is looping of "+j+" in "+i);
}
runNum = 1;
main.signal();//唤醒主线程
} catch (Exception e) {
// TODO: handle exception
} finally{
lock.unlock();
}
}
}
}

由此可见,Condition在多线程通信的强大作用,可以大大提高程序效率。

java多线程-Condition的更多相关文章

  1. Java多线程——Condition条件

    简介 Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signa ...

  2. Java多线程Condition定点通知

    多线程之间按顺序调用,实现A->B->C三个线程启动,要求如下:A打印5次,B打印10次,C打印15次接着 A打印5次,B打印10次,C打印15次 来10轮 package com.yan ...

  3. java多线程 -- Condition 控制线程通信

    Api文档如此定义: Condition 将 Object 监视器方法(wait.notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对 ...

  4. Java多线程系列--“JUC锁”06之 Condition条件

    概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition介绍Condition函数列表Condition示例转载请注明出处 ...

  5. Java多线程(九)之ReentrantLock与Condition

    一.ReentrantLock 类   1.1 什么是reentrantlock   java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 ...

  6. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  7. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

  8. Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例

    概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...

  9. Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock

    本章对ReentrantLock包进行基本介绍,这一章主要对ReentrantLock进行概括性的介绍,内容包括:ReentrantLock介绍ReentrantLock函数列表ReentrantLo ...

随机推荐

  1. LeetCode 2 Add Two Sum 解题报告

    LeetCode 2 Add Two Sum 解题报告 LeetCode第二题 Add Two Sum 首先我们看题目要求: You are given two linked lists repres ...

  2. 五个有用的jquery小技巧

    1.禁用鼠标右键 $(document).ready(function() { $(document).bind("contextmenu", function(e) { retu ...

  3. 为Unity项目生成文档(一)

    VS生成chm帮助文档 VS代码中使用Xml注释,并通过Sandcastle生成chm文档的文章,这几篇值得分享: 使用.NET中的XML注释(一) -- XML注释标签讲解 使用.NET中的XML注 ...

  4. IOS证书/私钥/代码签名/描述文件

    1.   相关资源 (1)   钥匙串程序(常用工具->钥匙串),用于创建证书请求.安装证书.导出私钥等 (2)   IOS开发中心:https://developer.apple.com/de ...

  5. 【MySQL】游标的具体使用详解

    测试表 level ; )); 再 insert 些数据 ;代码,初始化 drop procedure if exists useCursor // 建立 存储过程 create CREATE PRO ...

  6. CardboardCamera Prefab 中文笔记

    在Cardboard的预制体(Prefab)中, CardboardCamera是最简单的一个,仅有两个子物体,一个PostRender, 一个PreRender,以及分别带的Camera组件. Ca ...

  7. Protocol Buffer多态

    java中有多态的概念,protobuf本身没有多态的概念,但是它有一个扩展的概念. 以聊天消息为例,先看下面这个类图,基类是ChatMessage,子类TextMessage和ImageMessag ...

  8. [转]World Wind Java开发之四——搭建本地WMS服务器

    在提供地理信息系统客户端时,NASA还为用户提供了开源的WMS Server 服务器应用:World Wind WMS Server.利用这个应用,我们可以架设自己的WMS服务并使用自己的数据(也支持 ...

  9. EBS 用户及其联系人的失效时间

    联系人失效时间还有一个SQL,从页面的联系人详情简化取得的,不如直接用pos_supplier_users_v视图 SELECT * FROM (SELECT NULL contact_req_id, ...

  10. Android nDrawer

    GitHub上一款流行的侧滑,附上自己as编译过的源码http://download.csdn.net/detail/lj419855402/8559039. 留个纪念,说不定以后用得到. 依赖一个l ...