線程協作
-
存款/提款
- 提款金額大於存款金額:提款線程必須等待存款線程存錢
- 存款線程存入錢之後,通知提錢線程重新嘗試提錢,若餘額 < 提款金額,提款線程必須繼續等待新的存款
-
線程之間的相互協作
-
Condition
對象:await,signal(喚醒一個),signalAll(喚醒所有)- Condition 對象是通過調用Lock的newCondition()方法:創建
- 同一個條件對象調用signal和signalAll()方法喚醒等待的線程
-
-
調用await之後,lock對象會被釋放,喚醒存錢線程
- java5之前:對象的內置監視器(Object類的wait/signal/signalAll)
package Unit30.CorpThread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ThreadCooperation { private static Lock lock = new ReentrantLock(); private static Condition newDespoit = lock.newCondition(); private static class Acconut { private int balance = 0; public int getBalance() { return balance; } //取錢 private void withDraw(int amount) { try { lock.lock(); ; while (balance < amount) { System.out.print("\t\t\tWait for deposit"); /** * 和sleep不同,newDespoit.await();會導致當前線程掛起 * 同時鎖被釋放,否則存錢線程永遠無法進入deposit方法 * */ newDespoit.await(); } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } balance -= amount; System.out.println("\t\t\tWithDraw " + amount + "\t\t\t\t" + getBalance()); } //存錢 public void deposit(int amount) { try { lock.lock(); balance += amount; System.out.println("\t\t\tdeposit " + amount + " \t\t\t\t\t\t" + getBalance()); /** * 調用newDespoit.signalAll(); * 去喚醒所有因newDespoit.await();而掛起的線程 * */ newDespoit.signalAll(); } finally { lock.unlock(); } } } private static Acconut acconut = new Acconut(); public static class DepositTask implements Runnable { @Override public void run() { try { while (true) { acconut.deposit((int) (Math.random() * 10) + 1); Thread.sleep(5); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static class WithDrawTask implements Runnable { public void run() { while (true) { acconut.withDraw((int)(Math.random()*10)+1); } } } public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(2); executorService.execute(new DepositTask()); executorService.execute(new WithDrawTask()); executorService.shutdown(); System.out.println("Thread 1\t\t\t Thread \t\t\t\t Balance"); } }