银行取钱肯定不能透支这个是众所周知的,实现此功能就需要借助多线程的知识!
先来看一下采取同步措施前产生的结果:
好的,我们先来定义一个账户类:
/**
* 账户类,含卡号,还有余额 通过同步方法防止出现余额为负的情况
*
* @author Mr.Gao
*/
public class Account {
private String accountNo;
private double balance;
public Account(String accountNo, double balance) {
super();
this.accountNo = accountNo;
this.balance = balance;
}
public String getAccountNo() {
return accountNo;
}
public void setAccountNo(String accountNo) {
this.accountNo = accountNo;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((accountNo == null) ? 0 : accountNo.hashCode());
long temp;
temp = Double.doubleToLongBits(balance);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Account other = (Account) obj;
if (accountNo == null) {
if (other.accountNo != null)
return false;
} else if (!accountNo.equals(other.accountNo))
return false;
if (Double.doubleToLongBits(balance) != Double
.doubleToLongBits(other.balance))
return false;
return true;
}
public String toString() {
return "Account [accountNo=" + accountNo + ", balance=" + balance + "]";
}
/**
* 同步取钱方法,防止余额为负
* @param accountAmount
*/
public synchronized void draw(double accountAmount) {
if (balance > accountAmount) {
System.out.println(Thread.currentThread().getName() + " 取钱 "
+ accountAmount + " 成功");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
balance -= accountAmount;
System.out.println("余额为\t" + balance);
} else {
System.err.println("取钱失败");
}
}
}
定义一个线程类,主要演示同步方法,注释的部分为同步代码块的内容:
/**
* 取钱线程采用的是继承的方式
* 无须自己实现取钱的操作,直接调用account的draw()方法实现,符合"加锁--修改--释放锁"的逻辑
* 符合 领域驱动设计(每个类都是完整的领域对象,例如用户账户提供相应的方法去处理账户所对应的需求)
* @author Mr.Gao
*
*/
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() {
// synchronized (account) {
// if (account.getBalance() > drawAmount) {
// System.out.println(this.getName() + " 取钱 " + drawAmount
// + " 成功");
//
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// account.setBalance(account.getBalance() - drawAmount);
// System.out.println("余额为\t" + account.getBalance());
//
// } else {
// System.out.println("余额不足");
// }
// }
/*
* 直接调用account对象的draw()方法,同步方法的同步监视器是this,
* this代表调用draw()方法的对象,也就是说,再进入draw()方法前先对account对象进行加锁
*/
account.draw(drawAmount);
}
}
测试代码:
/**
* 结果测试
*
* @author Mr.Gao
*
*/
public class AccountTest {
public static void main(String[] args) {
Account acc = new Account("123", 1000);
new DrawThread("甲", acc, 800).start();
new DrawThread("乙", acc, 800).start();
}
}
输出效果: