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个线程中执行完特定任 ...
随机推荐
- Python探索记(17)——函数
# @Time : 2017/7/8 18:40 # @Author : 原创作者:谷哥的小弟 # @Site : 博客地址:http://blog.csdn.net/lfdfhl # @DESC : ...
- Mac安装并破解StarUML
1.下载与安装这里不做赘述,直接去官网下载即可 http://staruml.io/ 2.关键的事情来了,破解 一.打开安装包的目录 cd /Applications/StarUML.app/Cont ...
- Java 线程的中断机制
今天我们聊聊 Java 线程的中断机制. 线程中断机制提供了一种方法,用于将线程从阻塞等待中唤醒,并作出相应的“受控中断”处理. synchronized (lock) { try { while ( ...
- linux多线程全面解析
引入: 在传统的Unix模型中,当一个进程需要由另一个实体执行某件事时,该进程派生(fork)一个子进程,让子进程去进行处理.Unix下的大多数网络服务器程序都是这么编写的,即父进程接受连 ...
- php str_pad() 用法
$temp = str_pad(" ", 10000); for($i=0;$i<20;$i++){ echo $temp; echo $i; sle ...
- opencv之图像阈值化处理
一.函数简介 1.threshold-图像简单阈值化处理 函数原型:threshold(src, thresh, maxval, type, dst=None) src:图像矩阵 thresh:阈值 ...
- SQL中遇到多条相同内容只取一条的实现
例如出现BID为1673的两条重复数据,要第一条 select * from(select no=row_number() over(partition by Bid order by getdate ...
- kafka ksql && docker 安装试用
备注: 使用docker 模式进行安装 1. 准备docker 环境(需要docker-compose) docker 的安装不需要进行多描述了,直接yum 或者源码编译也可以 ...
- vue-router linkActiveClass问题
在使用vue做移动端的时候,底部四个菜单中当前菜单需要高亮显示,但是由于路由配置的问题导致了下图中的问题: # 首页会一直常亮,不论是否有点击(路由配置如右图) 经过排查,发现问题出现在router中 ...
- RelativeLayout里的gravity不能居中的解决方法
最近在遇到RelativeLayout里的gravity属性给它复制center_horizontal或者center都不能居中它的子组件,后来找到了替代方法,只要在它的每个子组件里加上android ...