1.使用线程同步机制,达到先支出后收入的效果。
1 public class AccountTest{ 2 3 public static void main(String[] args){ 4 final Account acc = new Account("John", 1000.0f); 5 acc.setWait(false); 6 7 DepositWorkerThread depositThread = new DepositWorkerThread("收入操作线程:", acc); 8 WithdrawWorkerThread withdrawThread = new WithdrawWorkerThread("支出操作线程:", acc); 9 10 depositThread.start(); 11 withdrawThread.start(); 12 13 // 让当前线程进行等待,上面两个线程执行完毕 14 try { 15 depositThread.join(); 16 withdrawThread.join(); 17 } catch (InterruptedException e) { 18 e.printStackTrace(); 19 } 20 System.out.println(Thread.currentThread().getName() + ": " + acc.getBalance()); 21 } 22 23 public static void RandomSleep(){ 24 Random random = new Random(); 25 try { 26 Thread.sleep(random.nextInt(3000)); 27 } catch (InterruptedException e) { 28 e.printStackTrace(); 29 } 30 } 31 } 32 33 /** 34 * 使用线程同步机制,达到先支出后收入的效果。 35 */ 36 // 对账户收入进行操作的线程 37 class DepositWorkerThread extends Thread{ 38 39 private Account account; 40 41 public DepositWorkerThread(String name, Account account){ 42 this.setName(name); 43 this.account = account; 44 } 45 46 @Override 47 public void run() { 48 49 // 准备工作,耗时 50 AccountTest.RandomSleep(); 51 52 synchronized (account) { 53 try { 54 if(!account.isWait()){ 55 account.wait(); 56 } 57 account.deposit(100.0f); 58 System.out.println(Thread.currentThread().getName() + ": " + this.account.getBalance()); 59 } catch (InterruptedException e) { 60 e.printStackTrace(); 61 } 62 } 63 } 64 } 65 66 // 对账户支出进行操作的线程 67 class WithdrawWorkerThread extends Thread{ 68 69 private Account account; 70 71 public WithdrawWorkerThread(String name, Account account){ 72 this.setName(name); 73 this.account = account; 74 } 75 76 @Override 77 public void run() { 78 79 // 准备工作,耗时 80 AccountTest.RandomSleep(); 81 82 synchronized (account) { 83 account.withdraw(100.0f); 84 System.out.println(Thread.currentThread().getName() + ": " + this.account.getBalance()); 85 account.setWait(true); 86 account.notify(); 87 } 88 } 89 } 90 91 92 class Account { 93 String name; 94 float amount; 95 boolean isWait; 96 97 public boolean isWait() { 98 return isWait; 99 } 100 101 public void setWait(boolean isWait) { 102 this.isWait = isWait; 103 } 104 105 public Account(String name, float amount) { 106 this.name = name; 107 this.amount = amount; 108 } 109 110 // 收入 111 public void deposit(float amt) { 112 float tmp = amount; 113 tmp += amt; 114 115 try { 116 Thread.sleep(100);//模拟其它处理所需要的时间,比如刷新数据库等 117 } catch (InterruptedException e) { 118 e.printStackTrace(); 119 } 120 121 amount = tmp; 122 } 123 124 // 支出 125 public void withdraw(float amt) { 126 float tmp = amount; 127 tmp -= amt; 128 129 try { 130 Thread.sleep(100);//模拟其它处理所需要的时间,比如刷新数据库等 131 } catch (InterruptedException e) { 132 e.printStackTrace(); 133 } 134 135 amount = tmp; 136 } 137 138 public float getBalance() { 139 return amount; 140 } 141 }
2. 使用线程同步机制,达到先收入后支出的效果。
1 public class AccountTest{ 2 3 public static void main(String[] args){ 4 final Account acc = new Account("John", 1000.0f); 5 acc.setWait(false); 6 7 DepositWorkerThread depositThread = new DepositWorkerThread("收入操作线程:", acc); 8 WithdrawWorkerThread withdrawThread = new WithdrawWorkerThread("支出操作线程:", acc); 9 10 depositThread.start(); 11 withdrawThread.start(); 12 13 // 让当前线程进行等待,上面两个线程执行完毕 14 try { 15 depositThread.join(); 16 withdrawThread.join(); 17 } catch (InterruptedException e) { 18 e.printStackTrace(); 19 } 20 System.out.println(Thread.currentThread().getName() + ": " + acc.getBalance()); 21 } 22 23 public static void RandomSleep(){ 24 Random random = new Random(); 25 try { 26 Thread.sleep(random.nextInt(3000)); 27 } catch (InterruptedException e) { 28 e.printStackTrace(); 29 } 30 } 31 } 32 33 /** 34 * 使用线程同步机制,达到先收入后支出的效果。 35 */ 36 // 对账户收入进行操作的线程 37 class DepositWorkerThread extends Thread{ 38 39 private Account account; 40 41 public DepositWorkerThread(String name, Account account){ 42 this.setName(name); 43 this.account = account; 44 } 45 46 @Override 47 public void run() { 48 49 // 准备工作,耗时 50 AccountTest.RandomSleep(); 51 52 synchronized (account) { 53 account.deposit(100.0f); 54 System.out.println(Thread.currentThread().getName() + ": " + this.account.getBalance()); 55 account.setWait(true); 56 account.notify(); 57 } 58 } 59 } 60 61 // 对账户支出进行操作的线程 62 class WithdrawWorkerThread extends Thread{ 63 64 private Account account; 65 66 public WithdrawWorkerThread(String name, Account account){ 67 this.setName(name); 68 this.account = account; 69 } 70 71 @Override 72 public void run() { 73 74 // 准备工作,耗时 75 AccountTest.RandomSleep(); 76 77 synchronized (account) { 78 try { 79 if(!account.isWait()){ 80 account.wait(); 81 } 82 account.withdraw(100.0f); 83 System.out.println(Thread.currentThread().getName() + ": " + this.account.getBalance()); 84 } catch (InterruptedException e) { 85 e.printStackTrace(); 86 } 87 } 88 } 89 } 90 91 92 class Account { 93 String name; 94 float amount; 95 boolean isWait; 96 97 public boolean isWait() { 98 return isWait; 99 } 100 101 public void setWait(boolean isWait) { 102 this.isWait = isWait; 103 } 104 105 public Account(String name, float amount) { 106 this.name = name; 107 this.amount = amount; 108 } 109 110 // 收入 111 public void deposit(float amt) { 112 float tmp = amount; 113 tmp += amt; 114 115 try { 116 Thread.sleep(100);//模拟其它处理所需要的时间,比如刷新数据库等 117 } catch (InterruptedException e) { 118 e.printStackTrace(); 119 } 120 121 amount = tmp; 122 } 123 124 // 支出 125 public void withdraw(float amt) { 126 float tmp = amount; 127 tmp -= amt; 128 129 try { 130 Thread.sleep(100);//模拟其它处理所需要的时间,比如刷新数据库等 131 } catch (InterruptedException e) { 132 e.printStackTrace(); 133 } 134 135 amount = tmp; 136 } 137 138 public float getBalance() { 139 return amount; 140 } 141 }
3. 不使用状态位来标志是否需要wait
1 public class AccountTest{ 2 3 public static void main(String[] args){ 4 final Account acc = new Account("John", 1000.0f); 5 // acc.setWait(false); 6 7 DepositWorkerThread depositThread = new DepositWorkerThread("收入操作线程:", acc); 8 WithdrawWorkerThread withdrawThread = new WithdrawWorkerThread("支出操作线程:", acc); 9 10 depositThread.start(); 11 withdrawThread.start(); 12 13 // 让当前线程进行等待,上面两个线程执行完毕 14 try { 15 depositThread.join(); 16 withdrawThread.join(); 17 } catch (InterruptedException e) { 18 e.printStackTrace(); 19 } 20 System.out.println(Thread.currentThread().getName() + ": " + acc.getBalance()); 21 } 22 23 public static void RandomSleep(){ 24 Random random = new Random(); 25 try { 26 Thread.sleep(random.nextInt(3000)); 27 } catch (InterruptedException e) { 28 e.printStackTrace(); 29 } 30 } 31 } 32 33 /** 34 * 使用线程同步机制,达到先收入后支出的效果。 35 */ 36 // 对账户收入进行操作的线程 37 class DepositWorkerThread extends Thread{ 38 39 private Account account; 40 41 public DepositWorkerThread(String name, Account account){ 42 this.setName(name); 43 this.account = account; 44 } 45 46 @Override 47 public void run() { 48 49 // 准备工作,耗时 50 AccountTest.RandomSleep(); 51 52 synchronized (account) { 53 account.deposit(100.0f); 54 System.out.println(Thread.currentThread().getName() + ": " + this.account.getBalance()); 55 // account.setWait(true); 56 account.notify(); 57 } 58 } 59 } 60 61 // 对账户支出进行操作的线程 62 class WithdrawWorkerThread extends Thread{ 63 64 private Account account; 65 66 public WithdrawWorkerThread(String name, Account account){ 67 this.setName(name); 68 this.account = account; 69 } 70 71 @Override 72 public void run() { 73 74 // 准备工作,耗时 75 AccountTest.RandomSleep(); 76 77 synchronized (account) { 78 try { 79 // 不使用状态位,判断是否需要调用 wait方法,就会出问题 80 // 例如:收入线程首先执行,则收入线程就调用了 notify 方法 81 // 此时,执行到这个方法时,调用 wait 方法。则由于没有线程会调用notify方法了, 82 // 则这个线程就不会被执行了, 83 // 当然也有可能上面的收入线程 执行完 account.deposit(100.0f); 之后被中断 84 // 然后下面的方法被执行,之后这个线程陷入等待状态,则上面的线程的 account.notify(); 得到调用 85 // 则下面的方法就返回了,所以,这种不使用状态位的情况下,就会有很多问题 86 // if(!account.isWait()){ 87 account.wait(); 88 // } 89 account.withdraw(100.0f); 90 System.out.println(Thread.currentThread().getName() + ": " + this.account.getBalance()); 91 } catch (InterruptedException e) { 92 e.printStackTrace(); 93 } 94 } 95 } 96 } 97 98 99 class Account { 100 String name; 101 float amount; 102 boolean isWait; 103 104 public boolean isWait() { 105 return isWait; 106 } 107 108 public void setWait(boolean isWait) { 109 this.isWait = isWait; 110 } 111 112 public Account(String name, float amount) { 113 this.name = name; 114 this.amount = amount; 115 } 116 117 // 收入 118 public void deposit(float amt) { 119 float tmp = amount; 120 tmp += amt; 121 122 try { 123 Thread.sleep(100);//模拟其它处理所需要的时间,比如刷新数据库等 124 } catch (InterruptedException e) { 125 e.printStackTrace(); 126 } 127 128 amount = tmp; 129 } 130 131 // 支出 132 public void withdraw(float amt) { 133 float tmp = amount; 134 tmp -= amt; 135 136 try { 137 Thread.sleep(100);//模拟其它处理所需要的时间,比如刷新数据库等 138 } catch (InterruptedException e) { 139 e.printStackTrace(); 140 } 141 142 amount = tmp; 143 } 144 145 public float getBalance() { 146 return amount; 147 } 148 }