线程协作
-
存款/提款
- 提款金额大于存款金额:提款线程必须等待存款线程存钱
- 存款线程存入钱之后,通知提钱线程重新尝试提钱,若余额 < 提款金额,提款线程必须继续等待新的存款
-
线程之间的相互协作
-
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"); } }