银行取钱肯定不能透支这个是众所周知的,实现此功能就需要借助多线程的知识!
先来看一下采取同步措施前产生的结果:
好的,我们先来定义一个账户类:
/** * 账户类,含卡号,还有余额 通过同步方法防止出现余额为负的情况 * * @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(); } } 输出效果: