1.Restaurant
package Produce; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; class Meal { private final int orderNum; public Meal(int orderNum) { this.orderNum = orderNum; } @Override public String toString() { return "Meal " + orderNum; } } class WaitPerson implements Runnable { private Restaurant restaurant; public WaitPerson(Restaurant r) { restaurant = r; } @Override public void run() { try { while (!Thread.interrupted()) { synchronized (this) { while (restaurant.meal == null) wait(); // 等待chef生产meal } System.out.println("Waitperson got " + restaurant.meal); synchronized (restaurant.chef) { restaurant.meal = null; restaurant.chef.notifyAll();// 通知chef继续生产 } } } catch (InterruptedException e) { System.out.println("WaitPerson interrupted"); } } } class Chef implements Runnable { private Restaurant restaurant; private int count = 0; public Chef(Restaurant r) { restaurant = r; } @Override public void run() { try { while (!Thread.interrupted()) { synchronized (this) { while (restaurant.meal != null) wait();// 等待meal被拿走 } if (++count == 10) { System.out.println("Out of food,closing"); restaurant.exec.shutdownNow();//向每个线程发送Interrupt return;//如果没有直接return 将多执行了下面的 Order up ,所以一般情况下都要直接return } System.out.println("Order up! "); synchronized (restaurant.waitPerson) { // 对notifyAll()的调用必须先获得waitPerson的锁 restaurant.meal = new Meal(count); restaurant.waitPerson.notifyAll(); } TimeUnit.MILLISECONDS.sleep(500);//休眠一下是为了给shutdownNow留出时间 } } catch (InterruptedException e) { System.out.println("Chef interrupted"); } } } public class Restaurant { Meal meal; ExecutorService exec = Executors.newCachedThreadPool(); WaitPerson waitPerson = new WaitPerson(this); Chef chef = new Chef(this); public Restaurant() { exec.execute(chef); exec.execute(waitPerson); } public static void main(String[] args) { new Restaurant(); } }
2.使用java.util.concurrent.locks.Condition进行同步操作
Lock和Condition对象只有在更加困难的多线程问题中才是必需的。
package Produce; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class Car { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); private boolean waxOn = false; public void waxed() { lock.lock(); try { waxOn = true;// Ready to buff condition.signalAll(); } finally { lock.unlock(); } } public void buffed() { lock.lock(); try { waxOn = false;// Ready for another coat of wax condition.signalAll(); } finally { lock.unlock(); } } public void waitForWaxing() throws InterruptedException { lock.lock(); try { while (waxOn == false) condition.await(); } finally { lock.unlock(); } } public void waitForBuffing() throws InterruptedException { lock.lock(); try { while (waxOn == true) condition.await(); } finally { lock.unlock(); } } } class WaxOn implements Runnable { private Car car; public WaxOn(Car c) { car = c; } @Override public void run() { try { while (!Thread.interrupted()) // while (true) //与使用这行效果一样 { System.out.println("Wax On!"); TimeUnit.MILLISECONDS.sleep(200); car.waxed(); car.waitForBuffing(); } } catch (InterruptedException e) { System.out.println("Exiting via interrupt"); } System.out.println("Ending Wax On task"); } } class WaxOff implements Runnable { private Car car; public WaxOff(Car c) { car = c; } @Override public void run() { try { while (!Thread.interrupted()) // while (true) { car.waitForWaxing(); System.out.println("Wax Off!"); TimeUnit.MILLISECONDS.sleep(200); car.buffed(); } } catch (InterruptedException e) { System.out.println("Exiting via interrupt"); } System.out.println("Ending Wax Off task"); } } public class WaxOMatic2 { public static void main(String[] args) throws InterruptedException { Car car = new Car(); ExecutorService exec = Executors.newCachedThreadPool(); exec.execute(new WaxOff(car)); exec.execute(new WaxOn(car)); TimeUnit.SECONDS.sleep(5); exec.shutdownNow(); } }