java 线程 condition_Java编程中实现Condition控制线程通信
java中控制线程通信的方法
1.传统的方式:利用synchronized关键字来保证同步,结合wait(),notify(),notifyall()控制线程通信。不灵活。
2.利用condition控制线程通信,灵活。
3.利用管道pipe进行线程通信,不推荐
4.利用blockingqueue控制线程通信
本文就讲解利用condition控制线程通信,非常灵活的方式。
condition类是用来保持lock对象的协调调用。
condition介绍
使用condition可以让那些已经得到lock对象却无法继续执行的线程释放lock对象,condition对象也可以唤醒处于等待的线程。
condition 将 object 监视器方法(wait、notify 和 notifyall)分解成截然不同的对象,以便通过将这些对象与任意 lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,lock 替代了 synchronized 方法和语句的使用,condition 替代了 object 监视器方法的使用。
condition 实例实质上被绑定到一个锁上。要为特定 lock 实例获得 condition 实例,使用其 newcondition() 方法。
condition类提供了如下三个方法:
await():造成当前线程在接到信号或被中断之前一直处于等待状态。 该方法流程:
1.新建condition node包装线程,加入condition队列。
2.释放当前线程占有的锁
3.阻塞当前线程
signal():唤醒当前lock对象的一个等待线程。signal方法只是将node(await方法封装的)修改了状态,并没有唤醒线程。要将修改状态后的node唤醒,一种是再次调用await(),一种是调用unlock()。//这局句很重要,不明白的可以看我下一篇博客。
signalall():唤醒当前lock对象的所有等待线程。只有当前线程放弃对lock的锁定,被唤醒的线程才可以执行。
代码实例:
代码逻辑:account类实现同步的取钱(draw)、存钱(deposit)操作;drawthread循环取钱的线程、depositthread循环存钱的线程。
account:
package condition;
import java.util.concurrent.locks.*;
/**
*存钱、取钱
*/
public class account
{
//显示定义lock对象
private final lock lock = new reentrantlock();//可重入锁
//获得指定lock对象对应的条件变量
private final condition cond = lock.newcondition(); //获得condition实例
private string accountno;
private double balance;
//标识账户中是否已经存款的旗标
private boolean flag = false;
public account(){}
public account(string accountno , double balance)
{
this.accountno = accountno;
this.balance = balance;
}
public void setaccountno(string accountno)
{
this.accountno = accountno;
}
public string getaccountno()
{
return this.accountno;
}
public double getbalance()
{
return this.balance;
}
/**
*取款
* @param drawamount
*/
public void draw(double drawamount)
{
//加锁
lock.lock();
system.out.println(thread.currentthread().getname() +"进入封锁区。。。。。。。。");
try
{
//如果账户中还没有存入存款,该线程等待
if (!flag)
{
cond.await();
}
else
{
//执行取钱操作
system.out.println(thread.currentthread().getname() +
" 取钱:" + drawamount);
balance -= drawamount;
system.out.println("账户余额为:" + balance);
//将标识是否成功存入存款的旗标设为false
flag = false;
//唤醒该lock对象对应的其他线程
cond.signalall();
}
}
catch (interruptedexception ex)
{
ex.printstacktrace();
}
//使用finally块来确保释放锁
finally
{
lock.unlock();
system.out.println("释放了");
}
}
/**
* 存款
* @param depositamount
*/
public void deposit(double depositamount)
{
lock.lock();
system.out.println(thread.currentthread().getname() +"进入封锁区。。。。。。。。");
try
{
//如果账户中已经存入了存款,该线程等待
if(flag)
{
system.out.println(thread.currentthread().getname() +"等待。。。。。。");
cond.await();
}
else
{
//执行存款操作
system.out.println(thread.currentthread().getname() +
" 存款:" + depositamount);
balance += depositamount;
system.out.println("账户余额为:" + balance);
//将标识是否成功存入存款的旗标设为true
flag = true;
//唤醒该lock对象对应的其他线程
cond.signalall();
}
}
catch (interruptedexception ex)
{
ex.printstacktrace();
}
//使用finally块来确保释放锁
finally
{
lock.unlock();
system.out.println(thread.currentthread().getname() +"释放锁。。。。");
}
}
public int hashcode()
{
return accountno.hashcode();
}
public boolean equals(object obj)
{
if (obj != null && obj.getclass() == account.class)
{
account target = (account)obj;
return target.getaccountno().equals(accountno);
}
return false;
}
}
drawthread:
package condition;
/**
*取钱
*/
public class drawthread extends thread
{
//模拟用户账户
private account account;
//当前取钱线程所希望取的钱数
private double drawamount;
public drawthread(string name , account account ,
double drawamount)
{
super(name);
this.account = account;
this.drawamount = drawamount;
}
//当多条线程修改同一个共享数据时,将涉及到数据安全问题。
public void run()
{
for (int i = 0 ; i < 6 ; i++ )
{
account.draw(drawamount);
}
}
}
depositthread:
package condition;
/**
*存钱
*/
public class depositthread extends thread
{
//模拟用户账户
private account account;
//当前取钱线程所希望取的钱数
private double depositamount;
public depositthread(string name , account account ,
double depositamount)
{
super(name);
this.account = account;
this.depositamount = depositamount;
}
//当多条线程修改同一个共享数据时,将涉及到数据安全问题。
public void run()
{
for (int i = 0 ; i < 2 ; i++ )
{
account.deposit(depositamount);
system.out.println(thread.currentthread().getname()+" 存钱结束!");
}
}
}
testdraw:
package condition;
public class testdraw
{
public static void main(string[] args)
{
//创建一个账户
account acct = new account("1234567" , 0);
new drawthread("取钱者" , acct , 800).start();
new depositthread("存钱者甲" , acct , 800).start();
new depositthread("存钱者乙" , acct , 800).start();
new depositthread("存钱者丙" , acct , 800).start();
}
}
运行结果:
取钱者进入封锁区。。。。。。。。
存钱者甲进入封锁区。。。。。。。。
存钱者甲 存款:800.0
账户余额为:800.0
存钱者甲释放锁。。。。
存钱者丙进入封锁区。。。。。。。。
存钱者甲 存钱结束!
存钱者丙等待。。。。。。
存钱者乙进入封锁区。。。。。。。。
存钱者乙等待。。。。。。
释放了
存钱者甲进入封锁区。。。。。。。。
存钱者甲等待。。。。。。
取钱者进入封锁区。。。。。。。。
取钱者 取钱:800.0
账户余额为:0.0
释放了
取钱者进入封锁区。。。。。。。。
这里结果只粘贴了一部分。。。。聪明的你会发现这个程序最后阻塞啦,注意是阻塞不是死锁!阻塞的原因是:三个存钱的线程都运行结束了,但是取钱的线程还没有,所以阻塞啦。
总结
以上就是本文关于java编程中实现condition控制线程通信的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:
有什么问题可以随时留言,小编会及时回复大家的。感谢朋友们对本站的支持!
如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!
java 线程 condition_Java编程中实现Condition控制线程通信相关推荐
- java condition详解_Java使用Condition控制线程通信的方法实例详解
Java使用Condition控制线程通信的方法实例详解 发布于 2020-4-20| 复制链接 摘记: 本文实例讲述了Java使用Condition控制线程通信的方法.分享给大家供大家参考,具体如下 ...
- 详解Java多线程编程中LockSupport类的线程阻塞用法
转载自 详解Java多线程编程中LockSupport类的线程阻塞用法 LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际 ...
- Java的并发编程中的多线程问题到底是怎么回事儿?
转载自 Java的并发编程中的多线程问题到底是怎么回事儿? 在我之前的一篇<再有人问你Java内存模型是什么,就把这篇文章发给他.>文章中,介绍了Java内存模型,通过这篇文章,大家应 ...
- 浅谈线程池(中):独立线程池的作用及IO线程池
在上一篇文章中,我们简单讨论了线程池的作用,以及CLR线程池的一些特性.不过关于线程池的基本概念还没有结束,这次我们再来补充一些必要的信息,有助于我们在程序中选择合适的使用方式. 独立线程池 上次我们 ...
- 【多线程】java 并发编程中的Condition对象-指定唤醒某个线程
1.概述 转载:java高并发系列 - 第13天:JUC中的Condition对象 synchronized中实现线程等待和唤醒 Condition简介及常用方法介绍及相关示例 使用Condition ...
- [转载] 解析Java的JNI编程中的对象引用与内存泄漏问题
参考链接: Java对象如何存储在内存中 JNI,Java Native Interface,是 native code 的编程接口.JNI 使 Java 代码程序可以与 native code 交互 ...
- jni jvm 内存泄漏_解析Java的JNI编程中的对象引用与内存泄漏问题
JNI,Java Native Interface,是 native code 的编程接口.JNI 使 Java 代码程序可以与 native code 交互--在 Java 程序中调用 native ...
- java的condition_java并发编程之Condition
引言 在java中,对于任意一个java对象,它都拥有一组定义在java.lang.Object上监视器方法,包括wait(),wait(long timeout),notify(),notifyAl ...
- 解析Java的JNI编程中的对象引用与内存泄漏问题
JNI,Java Native Interface,是 native code 的编程接口.JNI 使 Java 代码程序可以与 native code 交互--在 Java 程序中调用 native ...
最新文章
- 【poj3208-Apocalypse Someday】数位DP
- redis-server启动但进程里没有_Redis——服务器的启动过程
- linux知识(一) 程序、进程与线程
- 信息学奥赛一本通 ybt 1933:【05NOIP普及组】循环 | 洛谷 P1050 [NOIP2005 普及组] 循环
- css鼠标经过table文字变色,有没有可能用css实现当table被鼠标hover的时候,table列变色?...
- 思科路由器端口映射配置实例
- python有类似spring_Python的Spring与J的Spring相比
- drupal_prepare_form 大致是如何工作的 ?
- 极客学院 HTML5
- C#:数据库操作(待补充)
- linux下游戏制作工具,在Linux下可用Wine安装和运行D5Power游戏制作工具、蜂窝助手...
- 信息系统集成监理费收取标准_关于发布《信息系统工程监理及相关信息技术经验咨询服务取费计算办法(参照标准)》的通知...
- EXCEL表格-COUNTIF函数查找数据重复项
- matlab非齐次线性方程组的解,MATLAB求解非齐次线性方程组
- 定积分之旋转曲面的面积
- 棋牌游戏网站分析——远航游戏中心
- API文档工具knife4j使用详解
- 2020年最新手机处理器对比(附手机CPU天梯图)
- 关于Oracle索引的一点认识
- 你不再需要动态网页——编辑-发布-开发分离