Condition的功能类似在传统线程技术中的Object.wait()和Object.natify()的功能,传统线程技术实现的互斥只能一个线程单独干,不能说这个线程干完了通知另一个线程来干,Condition就是解决这个问题的,实现线程间的通信。比如CPU让小弟做事,小弟说我先歇着并通知大哥,大哥就开始做事。

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

Condition实例实质上被绑定到一个锁上。要为特定 Lock 实例获得 Condition 实例,请使用其 newCondition() 方法。

在java5中,一个锁可以有多个条件,每个条件上可以有多个线程等待,通过调用await()方法,可以让线程在该条件下等待。当调用signalAll()方法,又可以唤醒该条件下的等待的线程。

下面以银行存取款案例阐述Condition用法:

假设有一个账户,多个用户(线程)在同时操作这个账户,有的存款有的取款,存款随便存,取款有限制,不能透支,任何试图透支的操作都将等待里面有足够存款才执行操作。

package com.ljq.test.thread;

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) {
ConditionTest test = new ConditionTest(); // 创建并发访问的账户
Account myAccount = test.new Account("95599200901215522", 10000);
// 创建一个线程池
ExecutorService pool = Executors.newFixedThreadPool(2);
Thread t1 = test.new DrawThread("张三", myAccount, 11000);
Thread t2 = test.new SaveThread("李四", myAccount, 3600);
Thread t3 = test.new DrawThread("王五", myAccount, 2700);
Thread t4 = test.new SaveThread("老张", myAccount, 600);
Thread t5 = test.new DrawThread("老牛", myAccount, 1300);
Thread t6 = test.new SaveThread("胖子", myAccount, 2000); // 执行各个线程
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
pool.execute(t6);
// 关闭线程池
pool.shutdown();
} /**
* 存款线程类
*/
public class SaveThread extends Thread {
private String name; // 操作人
private Account account; // 账户
private int x; // 存款金额 SaveThread(String name, Account account, int x) {
this.name = name;
this.account = account;
this.x = x;
} public void run() {
account.saving(x, name);
}
} /**
* 取款线程类
*/
public class DrawThread extends Thread {
private String name; // 操作人
private Account account; // 账户
private int x; // 存款金额 DrawThread(String name, Account account, int x) {
this.name = name;
this.account = account;
this.x = x;
} public void run() {
account.drawing(x, name);
}
} /**
* 银行账户
*/
public class Account {
private String id; // 账号
private int cash; // 账户余额
private Lock lock = new ReentrantLock(); // 账户锁
private Condition _save = lock.newCondition(); // 存款条件
private Condition _draw = lock.newCondition(); // 取款条件 Account(String id, int cash) {
this.id = id;
this.cash = cash;
} /**
* 存款
*
* @param x 操作金额
* @param name 操作人
*/
public void saving(int x, String name) {
lock.lock(); // 获取锁
if (x > 0) {
cash += x; // 存款
System.out.println(name + "存款" + x + ",当前余额为" + cash);
}
_draw.signalAll(); // 唤醒所有等待的取款线程。
lock.unlock(); // 释放锁
} /**
* 取款
*
* @param x
* 操作金额
* @param name
* 操作人
*/
public void drawing(int x, String name) {
lock.lock(); // 获取锁
try {
if (cash - x < 0) {
System.out.println(name + "取款失败[余额不足],取款" + x + ",当前余额为" + cash);
_draw.await(); // 阻塞取款操作
} else {
cash -= x; // 取款
System.out.println(name + "取款" + x + ",当前余额为" + cash);
}
_save.signalAll(); // 唤醒所有等待的存款操作
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); // 释放锁
}
}
} }

  

java5 Condition用法--实现线程间的通信的更多相关文章

  1. Java-JUC(九):使用Lock替换synchronized,使用Condition的await,singal,singalall替换object的wait,notify,notifyall实现线程间的通信

    Condition: condition接口描述了可能会与锁有关的条件变量.这些用法上与使用object.wait访问隐式监视器类似,但提供了更强大的功能.需要特别指出的是,单个lock可能与多个Co ...

  2. Java:多线程,使用同步锁(Lock)时利用Condition类实现线程间通信

    如果程序不使用synchronized关键字来保证同步,而是直接使用Lock对象来保证同步,则系统中不存在隐式的同步监视器,也就不能用wait().notify().notifyAll()方法进行线程 ...

  3. QThread与其他线程间相互通信

    转载请注明链接与作者huihui1988 QThread的用法其实比较简单,只需要派生一个QThread的子类,实现其中的run虚函数就大功告成, 用的时候创建该类的实例,调用它的start方法即可. ...

  4. 关于synchronized和lock 的使用及其在线程间的通信

    题目要求:子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次 synchronized的使用 import java.util.conc ...

  5. 【转】Java学习---线程间的通信

    [原文]https://www.toutiao.com/i6572378564534993415/ 两个线程间的通信 这是我们之前的线程. 执行效果:谁抢到资源,谁运行~ 实现线程交替执行: 这里主要 ...

  6. Java多线程之线程的状态以及线程间协作通信导致的线程状态转换

      转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6561589.html  一:线程的状态以及变化图 Java中线程中状态可分为五种:New(新建状态),Ru ...

  7. 【转】Java学习:Java中的线程之线程间的通信

    hello各位小伙伴 今天我们来搞一下 线程之间的通信 ( • ̀ω•́ )✧ 让线程按照我们的想法来执行 两个线程间的通信 这是我们之前的线程. 执行效果:谁抢到资源,谁运行~ 实现线程交替执行: ...

  8. 并发编程系列小结(线程安全,synchronized,脏读,线程间的通信wait/notify,线程的三种实现方式Demo,可替代wait/notify的方法)

    线程安全: 当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法就是线程安全的) synchronized: 可以在任意对象或方法上加锁,而加锁的这段代码称为 ...

  9. iOS开发多线程篇—线程间的通信

    iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任 ...

随机推荐

  1. Linux系统下的shutdown命令用于安全的关闭/重启计算机

    Linux系统下的shutdown命令用于安全的关闭/重启计算机,它不仅可以方便的实现定时关机,还可以由用户决定关机时的相关参数.在执行shutdown命令时,系统会给每个终端(用户)发送一条屏显,提 ...

  2. 嵌入式中 ARM的几种工作模式 以及异常模式的优先级

    一.Arm工作模式: Arm微处理器支持7种工作模式,分别为: 1. 用户模式(Usr)            用于正常执行程序 2. 快速中断模式(FIQ)    用于高速数据传输 3. 外部中断模 ...

  3. oracle如何去除字段的回车换行符

    oracle如何去除字段的回车换行符? 可以用trim也可以用replace.区别在于,trim处理字符串两端,而replace中间也可以处理. trim select '全世界无产者 ' || '联 ...

  4. 对结合BDD进行DDD开发的一点思考和整理

    引言 二十年前的我,还在学校里抱着一台DIY机(德州486+大众主板+16M内存+3.5inch软驱+昆腾320M硬盘,当时全校最快主机没有之一),揣着一本<Undocumented DOS&g ...

  5. [STM32]HardFault 定位办法

    网上关于HardFault的定位办法好多,试到了其中一种可行的 http://www.cnblogs.com/Ilmen/p/3356147.html 特此纪录.

  6. HDU2032 杨辉三角

    解题思路:不要小看这题水题,如果数据类型没有用long long, 当n开为35时,会出现TLE,而且会报非法内存访问,现在还 不理解为什么,若有高手,请不吝赐教. 上代码: #include< ...

  7. python库之_thread

    官方参考文档:https://docs.python.org/3.7/library/_thread.html _thread库方法 (1) _thread.error (2)_thread.Lock ...

  8. Intent详解以及实例

    Android中统一用Intent来封装程序的“调用意图“.不管程序想启动一个Activity,一个Servicer,还是一个BroadcastReceiver.使用Intent提供了一个统一的编程模 ...

  9. Instruments检测解决内存泄露以及进行性能测试

    1.启动Xcode自带的Instruments.这里有两种方法启动. 方法一: 方法二: 2.选择Leaks选项.(该选项用来进行内存泄漏检测) 说明: Leaks:找到引发内存泄漏的起点. Time ...

  10. 转载 fpga中 restoring 和 non-restoring 除法实现。

    对于non-restoring方法,主要是用rem和den移位数据比较,rem_d长度为den+nom的总长,den_d长度为den+nom的总长度,rem_d的初始值为{{d_width{1'b0} ...