1. 定义

让有限的工作线程(Worker Thread)来轮流异步处理无限多的任务。也可以将其归类为分工模式,它的典型实现
就是线程池,也体现了经典设计模式中的享元模式。

2. 饥饿

固定大小线程池会有饥饿现象
两个工人是同一个线程池中的两个线程
他们要做的事情是:为客人点餐和到后厨做菜,这是两个阶段的工作
客人点餐:必须先点完餐,等菜做好,上菜,在此期间处理点餐的工人必须等待
后厨做菜:没啥说的,做就是了
比如工人A 处理了点餐任务,接下来它要等着 工人B 把菜做好,然后上菜,他俩也配合的蛮好
但现在同时来了两个客人,这个时候工人A 和工人B 都去处理点餐了,这时没人做饭了,饥饿

  1. public class TestStarvation {
  2. static final List<String> MENU = Arrays.asList("地三鲜", "宫保鸡丁", "辣子鸡丁", "烤鸡翅");
  3. static Random RANDOM = new Random();
  4. static String cooking() {
  5. return MENU.get(RANDOM.nextInt(MENU.size()));
  6. }
  7. public static void main(String[] args) {
  8. ExecutorService waiterPool = Executors.newFixedThreadPool(2);
  9. waiterPool.execute(() -> {
  10. System.out.println("处理点餐...");
  11. Future<String> f = waiterPool.submit(() -> {
  12. System.out.println("做菜");
  13. return cooking();
  14. });
  15. try {
  16. System.out.println("上菜: " + f.get());
  17. } catch (InterruptedException | ExecutionException e) {
  18. e.printStackTrace();
  19. }
  20. });
  21. waiterPool.execute(() -> {
  22. System.out.println("处理点餐...");
  23. Future<String> f = waiterPool.submit(() -> {
  24. System.out.println("做菜");
  25. return cooking();
  26. });
  27. try {
  28. System.out.println("上菜: " + f.get());
  29. } catch (InterruptedException | ExecutionException e) {
  30. e.printStackTrace();
  31. }
  32. });
  33. }
  34. }

image.png
解决方案:
不同的事交给不同线程池处理

  1. public class TestStarvation {
  2. static final List<String> MENU = Arrays.asList("地三鲜", "宫保鸡丁", "辣子鸡丁", "烤鸡翅");
  3. static Random RANDOM = new Random();
  4. static String cooking() {
  5. return MENU.get(RANDOM.nextInt(MENU.size()));
  6. }
  7. public static void main(String[] args) {
  8. ExecutorService waiterPool = Executors.newFixedThreadPool(2);
  9. ExecutorService cookPool = Executors.newFixedThreadPool(1);
  10. waiterPool.execute(() -> {
  11. System.out.println("处理点餐...");
  12. Future<String> f = cookPool.submit(() -> {
  13. System.out.println("做菜");
  14. return cooking();
  15. });
  16. try {
  17. System.out.println("上菜: " + f.get());
  18. } catch (InterruptedException | ExecutionException e) {
  19. e.printStackTrace();
  20. }
  21. });
  22. waiterPool.execute(() -> {
  23. System.out.println("处理点餐...");
  24. Future<String> f = cookPool.submit(() -> {
  25. System.out.println("做菜");
  26. return cooking();
  27. });
  28. try {
  29. System.out.println("上菜: " + f.get());
  30. } catch (InterruptedException | ExecutionException e) {
  31. e.printStackTrace();
  32. }
  33. });
  34. }
  35. }

image.png