下面代码模拟了一个存款和取款的逻辑,具体代码如下:
/** * * @version 1L * @author LinkinPark * @since 2015-2-5 * @motto 梦似烟花心似水,同学少年不言情 * @desc ^ 以后在编码中养成良好的习惯,要是一个类的某些属性不能随便更改的话,就不要提供set方法 */ public class Account { private String accountNo;//账户编号 private double balance;//账户余额 private boolean flag = false;//标识账户中是否已有存款的旗标 public Account() { } public Account(String accountNo, double balance) { this.accountNo = accountNo; this.balance = balance; } public void setAccountNo(String accountNo) { this.accountNo = accountNo; } public String getAccountNo() { return this.accountNo; } // 因此账户余额不允许随便修改,所以只为balance提供getter方法,不要提供set方法 public double getBalance() { return this.balance; } public synchronized void draw(double drawAmount) { try { // 如果flag为假,表明账户中还没有人存钱进去,取钱方法阻塞 if (!flag) { wait(); } else { // 执行取钱 System.out.println(Thread.currentThread().getName() + " 取钱:" + drawAmount); balance -= drawAmount; System.out.println("账户余额为:" + balance); // 将标识账户是否已有存款的旗标设为false。 flag = false; // 唤醒其他线程 notifyAll(); } } catch (InterruptedException ex) { ex.printStackTrace(); } } public synchronized void deposit(double depositAmount) { try { // 如果flag为真,表明账户中已有人存钱进去,则存钱方法阻塞 if (flag) { wait(); } else { // 执行存款 System.out.println(Thread.currentThread().getName() + " 存款:" + depositAmount); balance += depositAmount; System.out.println("账户余额为:" + balance); // 将表示账户是否已有存款的旗标设为true flag = true; // 唤醒其他线程 notifyAll(); } } catch (InterruptedException ex) { ex.printStackTrace(); } } // 下面两个方法根据accountNo来重写hashCode()和equals()方法 public int hashCode() { return accountNo.hashCode(); } public boolean equals(Object obj) { if (this == obj) return true; if (obj != null && obj.getClass() == Account.class) { Account target = (Account) obj; return target.getAccountNo().equals(accountNo); } return false; } }
/** * * @version 1L * @author LinkinPark * @since 2015-2-5 * @motto 梦似烟花心似水,同学少年不言情 * @desc ^ 取钱的线程 */ 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; } // 重复100次执行取钱操作 public void run() { for (int i = 0; i < 100; i++) { account.draw(drawAmount); } } }
/** * @version 1L * @author LinkinPark * @since 2015-2-5 * @motto 梦似烟花心似水,同学少年不言情 * @desc ^存钱的线程 */ 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; } // 重复100次执行存款操作 public void run() { for (int i = 0; i < 100; i++) { account.deposit(depositAmount); } } }
public class DrawTest { public static void main(String[] args) { // 创建一个账户 Account acct = new Account("NightWish", 0); new DrawThread("取钱者", acct, 800).start(); new DepositThread("存款者甲", acct, 800).start(); new DepositThread("存款者乙", acct, 800).start(); new DepositThread("存款者丙", acct, 800).start(); } }