账户文件
Account.java
public class Account {
private String accountNo;
private double balance;
//标识账户中是否已有存款
private boolean flag = false;
public Account(String accountNo,double balance)
{
this.accountNo = accountNo;
this.balance = balance;
}
public double getBalance()
{
return balance;
}
public String getAccount()
{
return accountNo;
}
public synchronized void draw(double drawAmount)
{
try {
//如果里面没钱,则等待(不能取钱)
if (!flag)
{
wait();
}
else {
//取钱
System.out.println(Thread.currentThread().getName()
+ "取钱成功!吐出钞票:"+drawAmount);
balance -= drawAmount;
System.out.println("\t余额为"+balance);
//取钱之后,设置为不能取钱
flag = false;
notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void deposit(double depositAmount)
{
try
{
if(flag)
{
//flag为true表示已经有人存钱,则等待(不能存钱)
wait();
}
else {
//可以存钱
System.out.println(Thread.currentThread().getName()
+"存钱成功"+depositAmount);
balance += depositAmount;
flag = true;
System.out.println("账户余额为:"+balance);
notifyAll();
}
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
public int hashCode()
{
return accountNo.hashCode();
}
//判断是否为同一个对象
public boolean equals(Object obj)
{
if (obj != null && obj.getClass() == Account.class)
{
Account target = (Account) obj;
return target.getAccount().equals(accountNo);
}
return false;
}
}
用于取钱的线程
DrawThread.java
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()
{
//模拟取钱操作
for(int i = 0;i<100;i++)
{
account.draw(drawAmount);
}
}
}
用于存钱的线程
DepositThread.java
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);
}
}
}
主程序
TestDraw.java
public class TestDraw {
public static void main(String[] args) {
Account acct = new Account("1234567", 0);
new DrawThread("取钱", acct, 800).start();
new DepositThread("存钱者甲", acct, 800).start();
new DepositThread("存钱者乙", acct, 800).start();
new DepositThread("存钱者丙", acct, 800).start();
}
}
程序运行时,三个存款者线程随机向一个账户中存钱,只有一个取款者线程执行取钱操作。只有当取款者取钱之后,存款者才能存钱。同样,只有当存款者存款之后,取款者才能取钱。
运行结果:
最后卡在了账户余额为800元,程序阻塞。
当使用Lock对象来保证同步时,程序改写为
Account.java
public class Account {
private String accountNo;
private double balance;
//标识账户中是否已有存款
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition cond = lock.newCondition();
public Account(String accountNo,double balance)
{
this.accountNo = accountNo;
this.balance = balance;
}
public double getBalance()
{
return balance;
}
public String getAccount()
{
return accountNo;
}
public synchronized 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();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
finally
{
lock.unlock();
}
}
public synchronized void deposit(double depositAmount)
{
lock.lock();
try
{
if(flag)
{
//flag为true表示已经有人存钱,则等待(不能存钱)
cond.await();
}
else {
//可以存钱
System.out.println(Thread.currentThread().getName()
+"存钱成功"+depositAmount);
balance += depositAmount;
flag = true;
System.out.println("账户余额为:"+balance);
cond.signalAll();
}
}
catch(InterruptedException e)
{
e.printStackTrace();
}
finally{lock.unlock();}
}
public int hashCode()
{
return accountNo.hashCode();
}
//判断是否为同一个对象
public boolean equals(Object obj)
{
if (obj != null && obj.getClass() == Account.class)
{
Account target = (Account) obj;
return target.getAccount().equals(accountNo);
}
return false;
}
}