Java基础:多线程间的通信


多个线程在处理同一个资源,但是线程的任务却不相同。例如生产者和消费者模式。假设有这样的一个系统,系统要求存钱者和取钱者不断重复存钱和取钱的两个动作,每当存钱者将钱存入指定账户后,取钱者就立即取出这笔钱。如何实现这样的要求,则需要利用线程通信机制。

线程通信的方式:

  • 传统的线程通信,使用synchronized关键字来保持同步
  • 使用Condition来控制线程通信:使用Lock对象来保持同步

传统的线程通信:使用synchronized关键字来保持同步

借助Object类提供的wait()、notify()、notifyall()三个方法。
关于这三个方法的解释如下:
wait(): 导致当前线程等待 ,直到其他线程调用该同步监视器的notify()或者notifyAll()方法来唤醒线程
notify(): 唤醒再次同步监视器上等待的线程。如果所有的线程都在此同步监视器上等待,则会选择唤醒其中一个线程,选择是随机的。
notifyAll() : 唤醒在此同步监视器上等待的所有线程。只有当前线程放弃对该同步监视器的锁定之后,才能执行唤醒线程操作。

那现在,我们如何去实现,重复存钱和重复取钱的操作。


public class DrawTest {
 public static void main(String[] args) {
  BankAccount bankAccount=new BankAccount("123bank", 0);
  new DrawThread("取钱者", bankAccount, 100).start();
  new DepositThread("存钱者甲", bankAccount, 100).start();
  new DepositThread("存钱者乙", bankAccount, 100).start();
  new DepositThread("存钱者丙", bankAccount, 100).start();
  
 }
   
}
class BankAccount{
 private String accountNo;
 private double balance;
 
 private boolean flag=false;
 public String getAccountNo() {
  return accountNo;
 }
 public void setAccountNo(String accountNo) {
  this.accountNo = accountNo;
 }
 public double getBalance() {
  return balance;
 }
public BankAccount(String accountNo,double balance) {
  // TODO Auto-generated constructor stub
  this.accountNo=accountNo;
  this.balance=balance;
 }
 //同步方法,取钱
 public synchronized void Draw(double drawingMoney) {
  try {
   //如果flag为false,则还没有人存钱进去,取钱方法等待
   if(!flag) {
    wait();
   }
   else {
    System.out.println(Thread.currentThread().getName()+"取钱"+drawingMoney);
    balance-=drawingMoney;
    System.out.println("账户余额为"+balance);
    flag=false;
    //唤醒其他线程
    notifyAll();
   }
   
  } catch (Exception e) {
   // TODO: handle exception
  }
  
    }
    //同步方法,存钱
 public synchronized void Deposit(double depositMoney) {
  try {
   //如果flag为true,说明还没有人取钱走,存钱线程等待
   if(flag) {
    wait();
   }
   else {
    System.out.println(Thread.currentThread().getName()+"存款"+depositMoney);
    balance+=depositMoney;
    System.out.println("账户余额为"+balance);
    flag=true;
    //唤醒其他线程
    notifyAll();
    
    
   }
   
  } catch (Exception e) {
   // TODO: handle exception
  }
  
       }
}
class DrawThread extends Thread{
 private BankAccount bankAccount;
 private double drawingMoney;
 //模拟用户取钱
 public DrawThread(String name,BankAccount bankAccount,double drawingMoney ) {
  // TODO Auto-generated constructor stub
  super(name);
  this.bankAccount=bankAccount;
  this.drawingMoney=drawingMoney;
 }
 @Override
 public void run() {
  // TODO Auto-generated method stub
  for(int i=0;i<10;i++) {
   bankAccount.Draw(drawingMoney);
  }
 }
}
class DepositThread extends Thread{
 private BankAccount bankAccount;
 private double depositMoney;
 //模拟用户存钱
 public DepositThread(String name,BankAccount bankAccount,double depositMoney ) {
  // TODO Auto-generated constructor stub
  super(name);
  this.bankAccount=bankAccount;
  this.depositMoney=depositMoney;
 }
 @Override
 public void run() {
  // TODO Auto-generated method stub
  for(int i=0;i<10;i++) {
   bankAccount.Deposit(depositMoney);
  }
 }
}
  
存钱者甲存款100.0
账户余额为100.0
取钱者取钱100.0
账户余额为0.0
存钱者丙存款100.0
账户余额为100.0
取钱者取钱100.0
账户余额为0.0
存钱者甲存款100.0
账户余额为100.0
取钱者取钱100.0
账户余额为0.0
存钱者甲存款100.0
账户余额为100.0
取钱者取钱100.0
账户余额为0.0
存钱者甲存款100.0
账户余额为100.0
取钱者取钱100.0
账户余额为0.0
存钱者甲存款100.0
账户余额为100.0

使用Condition来控制线程通信:使用Lock对象来保持同步

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值