java 多线程 9 : 使用Condition控制线程通信

如果程序不使用synchronized关键字来保证同步 , 直接使用Lock对象  , 则系统中不存在隐式的同步监视器 , 也就不能使用wait(),notify(),notifyAll()方法进行通信了

当使用Lock对象来保证同步时,使用Condition可以让那些已经得到Lock对象无法继续执行的线程释放Lock对象,Condition对象也可以唤醒其他处于等待的线程。

Lock替代了同步方法或者同步代码块 , Condition替代了同步监视器的功能

Condition实例被绑定在一个Lock对象上面, 要获得Lock实例的Condition实例 , 调用Lock对象的newCondition()方法即可。

await():类似于隐士同步监视器上面的wait()方法,使当前线程等待,知道其他线程使用该Condition的signal()方法或者signalAll()方法来唤醒该线程

signal(): 唤醒在此Lock对象上等待的单个线程,如果所有线程都在Lock对象上等待,则会选择唤醒任意一个。只有当前线程放弃对该Lock对象的锁定后(使用await()方法),才可以执行被唤醒的线程

signalAll():唤醒在此Lock对象上等待的所有线程,只有当前线程放弃对该Lock对象的锁定后才可以执行被唤醒的线程。

package com.example.demo.thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Account {
    //显示定义Lock对象
    private final Lock lock = new ReentrantLock();
    //获得指定Lock对象的对应Condition
    private final Condition condition = lock.newCondition();
    
    private String account;//账户
    private double balance;//余额
    
    private boolean flag = false; //标识是否已有存款 , 有为true

    public Account() {
        super();
        // TODO Auto-generated constructor stub
    }

    public Account(String account, double balance) {
        super();
        this.account = account;
        this.balance = balance;
    }
    //账户余额不允许随便修改 , 只提供getter方法
    public double getBalance() {
        return balance;
    }
    
    //取款
    public void draw(double drawMoney) {
        lock.lock();//加锁
        try {
            if(!flag) {//false说明没得存款 , 那就等待 咯
                condition.await();
            }else {
                System.out.println(Thread.currentThread().getName() + "取钱:" + drawMoney);
                //true 执行取钱的操作
                balance -= drawMoney;
                System.out.println("账户余额为:" + balance);
                //取完钱 , 改flag
                flag = false;
                //唤醒其他线程
                condition.signalAll();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();//释放锁
        }
    }
    
    //存钱
    public void save(double saveMoney) {
        lock.lock();//加锁
        try {
            if(flag) {//true 标识有人存钱了 , 存钱方法阻塞
                condition.await();
            }
            else {
                // false 没钱 , 开始存钱
                System.out.println(Thread.currentThread().getName()  + "存款:" + saveMoney);
                balance += saveMoney;
                System.out.println("账户余额为:" + balance);
                //存完钱 , 改flag 
                flag = true;
                //唤醒其他线程
                condition.signalAll();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();//放锁
        }
        
    }
    
    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }
}
package com.example.demo.thread;

public class DrawThread extends Thread{

    private Account account;//账号
    private double drawMoney;//想要划扣的钱
    
    public DrawThread(String name  , Account account, double drawMoney) {
        super(name);
        this.account = account;
        this.drawMoney = drawMoney;
    }
    
    public void run() {
        for(int i = 0 ; i < 100; i++) {//重复执行取钱的操作
            account.draw(drawMoney);
        }
    }
    
}
package com.example.demo.thread;

public class SaveThread extends Thread{

    private Account account;//账号
    private double saveMoney;//想要存的钱
    
    public SaveThread(String name , Account account , double saveMoney) {
        super(name);
        this.account = account;
        this.saveMoney = saveMoney;
    }
    
    public void run() {
        //重复执行存钱的操作
        for(int i = 0 ; i < 100 ; i++) {
            account.save(saveMoney);
        }
    }
    
}
package com.example.demo.thread;

public class Test {

    public static void main(String[] args) {
        Account account = new Account("123456",0);
        new DrawThread("取钱者:", account, 500).start();
        new SaveThread("存钱者-A", account, 500).start();
        new SaveThread("存钱者-B", account, 500).start();
        new SaveThread("存钱者-C", account, 500).start();
    }
}

猜你喜欢

转载自www.cnblogs.com/Uzai/p/9687206.html