文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java编程中实现Condition控制线程通信

2023-05-30 21:54

关注

java中控制线程通信的方法

传统的方式:利用synchronized关键字来保证同步,结合wait(),notify(),notifyAll()控制线程通信。不灵活。

利用Condition控制线程通信,灵活。

利用管道pipe进行线程通信,不推荐

利用BlockingQueue控制线程通信

本文就讲解利用Condition控制线程通信,非常灵活的方式。

Condition类是用来保持Lock对象的协调调用。

对Lock不了解的可以参考:Java线程同步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():造成当前线程在接到信号或被中断之前一直处于等待状态。 该方法流程:

新建Condition Node包装线程,加入Condition队列。

释放当前线程占有的锁

阻塞当前线程

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; }  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("释放了");  } }  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; }}

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 资料下载
  • 历年真题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯