Java多线程协调控制之wait¬ifyAll
来源:互联网 发布:刺马案 知乎 编辑:程序博客网 时间:2024/05/29 09:42
最近在复习Java基础,看到多线程这块顺便写写多线程的协调控制程序。
需求:假设系统中有两个线程分别代表取款者和存款者,现在系统的要求是存款者和取款者不断的重复存、取款操作,
并且要求每当有存款者将钱存入指定账户中时,取款者就立即取出这笔钱,即不允许存款者连续两次存钱,也不允许
取款者两次取钱。
下面代码实现:
1.首先是账户Account类;
package com.xjtu.cruise.soft.thread;public class Account {/** * @author Cruise * @param args */private String accountNo;//标识账户是否还有存款的private boolean flag = false;private double balance;public Account(){}public Account(String accountNo, double balance) {this.accountNo = accountNo;this.balance = balance;}public double getBalance(){return balance;}public synchronized void draw(double drawAmount) {try {if (!flag) { //如果账户没钱wait(); //阻塞当前的方法,并释放同步锁(这里就是this,也就是调用此方法的对象)} else {System.out.println("线程:" + Thread.currentThread().getName()+ "取款" + drawAmount);balance -= drawAmount;System.out.println("账户余额:" + balance);flag = false;notifyAll(); //唤醒等待此同步锁的所有线程}} catch (InterruptedException e) {e.printStackTrace();}}public synchronized void deposit(double depositAmount) {try{if(flag){ //如果账户有存入的钱wait();}else{System.out.println("线程:"+ Thread.currentThread().getName()+"存款"+depositAmount);balance += depositAmount;System.out.println("账户余额:" + balance);flag = true;notifyAll();}}catch(InterruptedException e){e.printStackTrace();}}}
2.接下来是存取款线程类(DrawThread,DepositThread)
package com.xjtu.cruise.soft.thread;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<100; i++){//System.out.println("线程:" + Thread.currentThread().getName()+"执行存款操作。");account.deposit(depositAmount);}}}
package com.xjtu.cruise.soft.thread;public class DrawThread extends Thread {/** * @author Cruise * @param args */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<100; i++){//System.out.println("线程:" + Thread.currentThread().getName()+"执行取钱操作。");account.draw(drawAmount);}}}
3.奉上测试类TestDraw
package com.xjtu.cruise.soft.thread;public class TestDraw {/** * @author Cruise * @param args */public static void main(String[] args) {Account account = new Account("123", 0);new DrawThread("取钱者", account, 800).start();new DepositThread("存款者甲",account, 800).start();new DepositThread("存款者乙",account, 800).start();}}
OK, 一个使用wait和notifyAll控制线程协调的Demo完成,运行结果如下:
下面再使用条件变量的方式来协调线程的同步,具体来说就是使用Lock对象来保证同步,而不是用Synchronized关键字。
通过Lock实例来调用其newCondition()方法得到对应的Condition对象,接着使用此Condition实例的方法来保证线程的协
调。这里用到了Condition的await和signalAll方法。
将上面的Account类修改如下,其他的线程类不变。
package com.xjtu.cruise.soft.thread;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class Account {/** * @author Cruise * @param args */private final Lock lock = new ReentrantLock();//定义Lock对象private final Condition cond = lock.newCondition();//获取Lock对象对应的条件变量private String accountNo;//标识账户是否还有存款的private boolean flag = false;private double balance;public Account(){}public Account(String accountNo, double balance) {this.accountNo = accountNo;this.balance = balance;}public double getBalance(){return balance;}public void draw(double drawAmount) {lock.lock();//加锁try {if (!flag) { //如果账户没钱cond.await(); } else {System.out.println("线程:" + Thread.currentThread().getName()+ "取款" + drawAmount);balance -= drawAmount;System.out.println("账户余额:" + balance);flag = false;cond.signalAll(); //唤醒该Lock对象对应的其他线程}} catch (InterruptedException e) {e.printStackTrace();}finally{lock.unlock();//使用finally块确保释放锁}}public void deposit(double depositAmount) {lock.lock();//加锁try{if(flag){ //如果账户有存入的钱cond.await();}else{System.out.println("线程:"+ Thread.currentThread().getName()+"存款"+depositAmount);balance += depositAmount;System.out.println("账户余额:" + balance);flag = true;cond.signalAll();//唤醒该Lock对象对应的其他线程}}catch(InterruptedException e){e.printStackTrace();}finally{//使用finally块确保释放锁lock.unlock();}}}
运行上面的测试类,可以得到如下的运行结果:
从上面的两个运行结果可以发现,虽然两种方法都可以保证线程的同步和协调运行,但是线程的调度机制还是有些许的
差别,这点可以从上图的红框看出。当然底层的具体实现,因为不大了解,这里就不作具体的阐述了(废话,不了解当
然阐述不了,^_^),希望了解的同学能帮忙解答下,very thx!
0 0
- Java多线程协调控制之wait¬ifyAll
- java多线程之 wait(),notify(),notifyAll()
- java多线程之 wait(),notify(),notifyAll() 整理
- Java多线程之wait(),notify(),notifyAll()
- java多线程之 wait(),notify(),notifyAll()[迁]
- Java多线程之wait(),notify(),notifyAll()
- Java多线程之wait(),notify(),notifyAll() .
- Java多线程之synchronized,wait(),notify(),notifyAll()
- Java多线程之wait(),notify(),notifyAll()
- Java多线程之wait(),notify(),notifyAll()
- Java多线程之wait(),notify(),notifyAll()
- Java多线程之wait(),notify(),notifyAll()
- Java多线程之wait(),notify(),notifyAll()
- Java多线程之wait(),notify(),notifyAll()
- Java多线程之wait(),notify(),notifyAll()
- Java多线程之wait(),notify(),notifyAll()
- Java多线程之wait()、notify()、notifyAll()
- Java多线程之wait(),notify(),notifyAll()
- java RMI技术事例
- 安卓传感器 Sensor
- UVA 563 Crimewave (最大流,拆点)
- 求旋转有序数组的最小值和在旋转数组中查找
- Linux 下 cpu的负载
- Java多线程协调控制之wait¬ifyAll
- 各种Parentheses
- QTP/UFT11.5官方下载与安装教程及汉化
- Qt中停靠窗口的实现
- 别再用JS里面的Math.random()方法生成随机数
- html学习笔记(一)——什么是html及html标签
- 关于ios中的setNeedsDisplay和setNeedsLayout
- [LeetCOde]Reverse Nodes in k-Group
- 局域网内查找固定ip插口所绑定的ip地址(linux)