多线程通信经典问题:存取钱问题

几天前在看到多线程通信问题的时候,觉得还挺头疼的,后来就画了一张图,之后就只能慢慢理解了.
这道题是这么规定的:两人,一人负责存款,一人负责取款;每次只要一存款就必须把钱取走;不能存钱两次,也不能取钱两次.

据分析,这个问题里面需要以下部分:

  1. 判断账户里面是否可以存钱(账户为空);
  2. 需要判断账户是否可以取钱;
  3. 之后需要判断一些余额什么的.

因此得出:

  • 对于存钱以及取钱的判断可以使用一个boolean变量来完成.
  • 由于多线程环境本身的不确定性,因此需要使用synchronized对存取钱方法进行同步.
  • *:给予money(钱,用于记录余额)一个get方法,但不用给予set方法.

如果没看明白上面的文字描述,可以看下面的图:

多线程通信经典问题
image-1760

懒得说了,直接甩源代码把,这个是我昨晚写的,大家可以适当进行改写,主要是理解里面的思想就行.


package com.w1520.Thread;

/**
* 模拟实现存取款功能.[每次需要先存钱,然后立刻取走,也就是账户里不能有钱]
* 同时不能存两次,也不能取两次.
*
* @author puruidong
* @version 2013.4.19
*/

public class Account {

private double money ;

public Account(double money){
this.money=money;
}

public double getMoney(){ //这样的方法很稳定.
return this.money;
}

private static boolean flag = false ; //定义游标来测试是否已经有存款

/*
* 存钱方法.
*/
public synchronized void set (String name,double setm){
if(flag){//如果为true表示里面有钱还没有被取走,让此线程等待.
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
this.money+=setm;//存款.
flag=true; //修改为已经将钱取走.
System.out.println(name+"恭喜您!存款成功!存款金额:"+setm+"余额:"+getMoney());
notifyAll();//唤醒所有正在睡眠的线程.
}

}
/*
* 取钱方法.
*/
public synchronized void get (String name , double getm){
if (flag==false){//如果为false表示里面没钱,不能取,让此线程等待.
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//
}else{

if(getMoney()>=getm){ //比较余额是不是足够.
flag = false; //修改为钱已取走.
notifyAll(); //唤醒所有在睡眠的线程.
this.money-=getm; //扣钱.
System.out.println(name+"恭喜您!取款成功!余额是:"+getMoney());
}else{
System.out.println(name+"抱歉余额不足!"+getMoney());
}
}
}

public static void main (String[]args){

Account a = new Account(0);//初始账户里没钱.
/*
* 必须使用同一个对象,否则将不能对账户进行操作!
*/
new A(a).start();
new B(a).start();
}
}

class A extends Thread {
final Account a ; //"保证"不变.

public A(final Account a){
this.a=a;
}

public void run (){
while(true){
a.set("<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", 800);
}
}

}

《多线程通信经典问题:存取钱问题》上有1条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据