在学习多线程的时候,有一个比较经典的例子是讲银行里的账号,假如存在多位取款者及存款者,在这里就涉及到线程锁及线程之间的通讯,但大部分的例子人讲了金额为1000,每次存取只有800,并且存完了就通知取的人,取完了就通知存的人。存款人及取款人均为一位。
个人在模拟这个问题的时候有将问题复杂化,假定有多位存款者,及取款者,当余额<=要取的钱的时候取款者不能取款,而当余额+ 存款值大于某一个值的时候不允许存款。
账户中存取款方法的代码
public synchronized void draw(double drawAccount){
try{
if(drawAccount > blance){
System.out.println(Thread.currentThread().getName() + "余额不足");
wait();
}
else{
System.out.println("\t" + Thread.currentThread().getName() + "取钱" + drawAccount);
blance -= drawAccount;
System.out.println("\t" + "账号余额: " + blance);
if(drawAccount > blance){
notifyAll();
}
}
}catch (InterruptedException ie){
ie.printStackTrace();
}
}
public synchronized void deposit(double depositAccout){
try{
if((blance + depositAccout) > total){
System.out.println(Thread.currentThread().getName() + "已到最高");
wait();
}else{
System.out.println(Thread.currentThread().getName() + "存钱" + depositAccout);
blance += depositAccout;
System.out.println("账号余额" + blance);
if((blance + depositAccout) > total){
notifyAll();
}
}
}catch (InterruptedException ie){
ie.printStackTrace();
}
}
取款线程
取款5次
public void run(){
for(int i = 0; i < 5; i++){
//System.out.println(getName() + "取钱");
System.out.println("\t" + getName() + i);
account.draw(drawAccount);
}
}
存款线程
存款5次
public void run(){
for(int i = 0; i < 5; i++){
//System.out.println(getName() + "存钱");
System.out.println(getName() + i);
account.deposit(depositAccount);
}
}
主线程
模拟2位取款者及2位取款者
public class DrawTest {
public static void main(String[] args) {
Account acct = new Account("12345", 1000);
new DrawThread("取钱者c", acct, 800).start();
new DrawThread("取钱者d", acct, 800).start();
new DepositThread("存钱者A", acct, 800).start();
new DepositThread("存钱者B", acct, 800).start();
}
}
按照我最开始的理解,最后的余额应该为1000才对,因为2位取款者各取5次,2位存款者各存5次。
但实际运行结果通常都不是1000
例如 :
账号余额: 1800.0
这说明某位取款者少取了 一次,后来对于每个取款者的每次操作打印分析,发现以下一点:
取钱者d3
取钱者d余额不足
取钱者d4
取钱者d取钱800.0
账号余额: 1800.0
问题就了在这里,取款者d在进行第4次取款的时候失败,也就是说if为真没有进入到else里面,但for循环还是将其算作一次取款,所以才导致最终的余额不为1000。