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控制线程通信相关推荐

  1. java condition详解_Java使用Condition控制线程通信的方法实例详解

    Java使用Condition控制线程通信的方法实例详解 发布于 2020-4-20| 复制链接 摘记: 本文实例讲述了Java使用Condition控制线程通信的方法.分享给大家供大家参考,具体如下 ...

  2. 详解Java多线程编程中LockSupport类的线程阻塞用法

    转载自  详解Java多线程编程中LockSupport类的线程阻塞用法 LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际 ...

  3. Java的并发编程中的多线程问题到底是怎么回事儿?

    转载自   Java的并发编程中的多线程问题到底是怎么回事儿? 在我之前的一篇<再有人问你Java内存模型是什么,就把这篇文章发给他.>文章中,介绍了Java内存模型,通过这篇文章,大家应 ...

  4. 浅谈线程池(中):独立线程池的作用及IO线程池

    在上一篇文章中,我们简单讨论了线程池的作用,以及CLR线程池的一些特性.不过关于线程池的基本概念还没有结束,这次我们再来补充一些必要的信息,有助于我们在程序中选择合适的使用方式. 独立线程池 上次我们 ...

  5. 【多线程】java 并发编程中的Condition对象-指定唤醒某个线程

    1.概述 转载:java高并发系列 - 第13天:JUC中的Condition对象 synchronized中实现线程等待和唤醒 Condition简介及常用方法介绍及相关示例 使用Condition ...

  6. [转载] 解析Java的JNI编程中的对象引用与内存泄漏问题

    参考链接: Java对象如何存储在内存中 JNI,Java Native Interface,是 native code 的编程接口.JNI 使 Java 代码程序可以与 native code 交互 ...

  7. jni jvm 内存泄漏_解析Java的JNI编程中的对象引用与内存泄漏问题

    JNI,Java Native Interface,是 native code 的编程接口.JNI 使 Java 代码程序可以与 native code 交互--在 Java 程序中调用 native ...

  8. java的condition_java并发编程之Condition

    引言 在java中,对于任意一个java对象,它都拥有一组定义在java.lang.Object上监视器方法,包括wait(),wait(long timeout),notify(),notifyAl ...

  9. 解析Java的JNI编程中的对象引用与内存泄漏问题

    JNI,Java Native Interface,是 native code 的编程接口.JNI 使 Java 代码程序可以与 native code 交互--在 Java 程序中调用 native ...

最新文章

  1. 【poj3208-Apocalypse Someday】数位DP
  2. redis-server启动但进程里没有_Redis——服务器的启动过程
  3. linux知识(一) 程序、进程与线程
  4. 信息学奥赛一本通 ybt 1933:【05NOIP普及组】循环 | 洛谷 P1050 [NOIP2005 普及组] 循环
  5. css鼠标经过table文字变色,有没有可能用css实现当table被鼠标hover的时候,table列变色?...
  6. 思科路由器端口映射配置实例
  7. python有类似spring_Python的Spring与J的Spring相比
  8. drupal_prepare_form 大致是如何工作的 ?
  9. 极客学院 HTML5
  10. C#:数据库操作(待补充)
  11. linux下游戏制作工具,在Linux下可用Wine安装和运行D5Power游戏制作工具、蜂窝助手...
  12. 信息系统集成监理费收取标准_关于发布《信息系统工程监理及相关信息技术经验咨询服务取费计算办法(参照标准)》的通知...
  13. EXCEL表格-COUNTIF函数查找数据重复项
  14. matlab非齐次线性方程组的解,MATLAB求解非齐次线性方程组
  15. 定积分之旋转曲面的面积
  16. 棋牌游戏网站分析——远航游戏中心
  17. API文档工具knife4j使用详解
  18. 2020年最新手机处理器对比(附手机CPU天梯图)
  19. 关于Oracle索引的一点认识
  20. 你不再需要动态网页——编辑-发布-开发分离

热门文章

  1. Win32项目生成的程序exe图标显示异常的问题
  2. 安卓Service完全解析(中)
  3. POJ-2135 Farm Tour 最小费用流
  4. iText 生成复杂表格
  5. 分享一个自己做的简易敏捷开发管理工具——AgileLite
  6. 在linux vi中激活鼠标中键,实现滚动换行
  7. hql将指定字段排在最后,然后再根据别的字段排序
  8. java基础问题集锦一
  9. 解决ubuntu下修改环境变量profile后报错,很多常用命令都用不了
  10. Ajax异步获取html数据中包含js方法无效的解决方法