1.银行账户类
package com.bankAccount.test;
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 cond=lock.newCondition();
//封装账户编号,账户余额的两个成员变量
private String accoutNo;
private double balance;
//标识账户中是否已有存款的旗标
private boolean flag=false;
public Account(){}
//构造器
public Account(String accountNo,double balance)
{
this.accoutNo=accountNo;
this.balance=balance;
}
public String getAccoutNo() {
return accoutNo;
}
public void setAccoutNo(String accoutNo) {
this.accoutNo = accoutNo;
}
//因为账户余额不可以随便修改,所以只为balance提供getter方法
public double getBalance() {
return this.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);
//将标识账户是否已有存款的旗标设为false
flag=false;
//唤醒其他进程
cond.signalAll();
}
}
catch(InterruptedException ex)
{
ex.printStackTrace();
}
finally
{
lock.unlock();
}
}
public void deposit(double depositAmount)
{
lock.lock();
try{
//如果flag为真,表明账户中已经有人存钱进去,存钱方法阻塞
if(flag)
{
cond.await();
}
else
{
//执行存款操作
System.out.println(Thread.currentThread().getName()+
"存款:"+depositAmount);
balance+=depositAmount;
System.out.println("账户余额为:"+balance);
//将表示是否已有存款的旗标设为true
flag=true;
//唤醒其他线程
cond.signalAll();
}
}
catch(InterruptedException ex)
{
ex.printStackTrace();
}
finally{
lock.unlock();
}
}
public int hashCode()
{
return accoutNo.hashCode();
}
public boolean equals(Object obj)
{
if(this==obj)
return true;
if(obj!=null&&obj.getClass()==Account.class)
{
Account target=(Account)obj;
return target.getAccoutNo().equals(accoutNo);
}
return false;
}
}
2.存款线程
package com.bankAccount.test;
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++)
{
account.deposit(depositAmount);
}
}
}
3.取款线程
package com.bankAccount.test;
public class DrawThread extends Thread{
//模拟用户账户
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()
{
//使用account作为同步监视器,任何线程进入下面同步代码块之前
//必须先获得对account账户的锁定---其他线程无法获得锁,也就无法修改它
//该做法符合:"加锁->修改->释放锁"
for(int i=0;i<100;i++)
{
account.draw(drawAmount);
}
}
}
4.测试类
package com.bankAccount.test;
public class DrawTest {
public static void main(String[] args) {
//创建一个账户
Account acct=new Account("123",0);
//模拟两个线程对同一个账户取 钱
new DrawThread("取钱者",acct,800).start();
new DepositThread("存款者甲",acct,800).start();
new DepositThread("存款者乙",acct,800).start();
new DepositThread("存款者丙",acct,800).start();
}
}
结果: