java5 Condition用法--实现线程间的通信
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用法--实现线程间的通信的更多相关文章
- Java-JUC(九):使用Lock替换synchronized,使用Condition的await,singal,singalall替换object的wait,notify,notifyall实现线程间的通信
Condition: condition接口描述了可能会与锁有关的条件变量.这些用法上与使用object.wait访问隐式监视器类似,但提供了更强大的功能.需要特别指出的是,单个lock可能与多个Co ...
- Java:多线程,使用同步锁(Lock)时利用Condition类实现线程间通信
如果程序不使用synchronized关键字来保证同步,而是直接使用Lock对象来保证同步,则系统中不存在隐式的同步监视器,也就不能用wait().notify().notifyAll()方法进行线程 ...
- QThread与其他线程间相互通信
转载请注明链接与作者huihui1988 QThread的用法其实比较简单,只需要派生一个QThread的子类,实现其中的run虚函数就大功告成, 用的时候创建该类的实例,调用它的start方法即可. ...
- 关于synchronized和lock 的使用及其在线程间的通信
题目要求:子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次 synchronized的使用 import java.util.conc ...
- 【转】Java学习---线程间的通信
[原文]https://www.toutiao.com/i6572378564534993415/ 两个线程间的通信 这是我们之前的线程. 执行效果:谁抢到资源,谁运行~ 实现线程交替执行: 这里主要 ...
- Java多线程之线程的状态以及线程间协作通信导致的线程状态转换
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6561589.html 一:线程的状态以及变化图 Java中线程中状态可分为五种:New(新建状态),Ru ...
- 【转】Java学习:Java中的线程之线程间的通信
hello各位小伙伴 今天我们来搞一下 线程之间的通信 ( • ̀ω•́ )✧ 让线程按照我们的想法来执行 两个线程间的通信 这是我们之前的线程. 执行效果:谁抢到资源,谁运行~ 实现线程交替执行: ...
- 并发编程系列小结(线程安全,synchronized,脏读,线程间的通信wait/notify,线程的三种实现方式Demo,可替代wait/notify的方法)
线程安全: 当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法就是线程安全的) synchronized: 可以在任意对象或方法上加锁,而加锁的这段代码称为 ...
- iOS开发多线程篇—线程间的通信
iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任 ...
随机推荐
- React Native探索(五)使用fetch进行网络请求
相关文章 React Native探索系列 前言 React Native可以使用多种方式来请求网络,比如fetch.XMLHttpRequest以及基于它们封装的框架,fetch可以说是替代XMLH ...
- 实战JAVA 高并发设计
一.同步(Synchronous)和异步(Asynchronous) 同步和异步通常用来形容一次方法调用,同步方法,调用者必须等到方法调用返回后,才能继续后续的行为,异步方法调用会立即返回,调用者就可 ...
- Ubuntu命令:sudo、shutdown、apt-get、vim
切换成ROOT用户: Ubuntu中默认不开启root账户,所以root账户是没有密码的, 但是会有一个非root的管理员账户,可以通过sudo来获得root权限,现在就可以用这个账户来设置密码 ** ...
- bzoj 1264 基因匹配
Written with StackEdit. Description 卡卡昨天晚上做梦梦见他和可可来到了另外一个星球,这个星球上生物的\(DNA\)序列由无数种碱基排列而成(地球上只有\(4\)种) ...
- bzoj 5369 最大前缀和
Written with StackEdit. Description 小\(C\)是一个算法竞赛爱好者,有一天小\(C\)遇到了一个非常难的问题:求一个序列的最大子段和. 但是小\(C\)并不会做这 ...
- Thinking in Java 4th(Java编程思想第四版)文档、源码、习题答案
Thinking in Java 4th 中.英文两版pdf文档,书中源码及课后习题答案.链接:https://pan.baidu.com/s/1BKJdtgJ3s-_rN1OB4rpLTQ 密码:2 ...
- pmm监控页面502
我们知道pmm主要使用的是 普罗米修斯采集和grafana日志统计显示. 最近为硬盘扩过一次容量,主要是docker使用的,我的pmm是跑在docker上的,但是重启后pmm的debug日志下载502 ...
- Mybatis与Hibernate的详细对比
前言 这篇博文我们重点分析一下Mybatis与hibernate的区别,当然在前面的博文中我们已经深入的研究了Mybatis和Hibernate的原理. Mybatis [持久化框架]Mybatis简 ...
- struts1和struts2原理解析
1.struts1和struts2 是2个完全不同的框架 其实struts2核心就是 webwork框架 struts1以ActionServlet作为核心控制器,由ActionServlet负责拦截 ...
- 遇到eclipse安装插件一直报错问题(版本问题)
刚好用了一个插件,然后在线安装报错了,一直报错,之前用的这个插件是直接解压贴的,现在在线安装出错,就很尬,我又有点懒,不想再去下载,贴,所以查了下,有网友说是eclipse的插件版本问题,更新了下,成 ...