这个模式是我们最熟悉的模式了,一边可劲的造,一边可劲的吃。

    image.png

    image.png

    那么这个模式的核心是什么呢?我按从左往右放,你从右往左拿。莫要乱了顺序。就不能从左往右拿吗?其实也是可以的,哈哈,怎么拿都随你,但是不同方法的算法不同罢了。无所谓。

    关键点就是满了就不能放了,空了就不能拿了。

    我们明确一个条件:先进先出,就是先创建的先消费,以免放坏,我们用不同的符号来表示拿的和放的位置。

    情景:幼儿园老师现场给小朋友们做蛋糕,烤好一个就往桌子的盘子里放一个,假设桌子总共可以放 5 个。小朋友5个,做面包的老师2个。老师大概2分钟做一个,小朋友大概3、5分钟吃一个.

    首先我们需要创建这个神奇的桌子。

    老师放蛋糕的时候,就不要考虑小朋友拿到了哪一个,只考虑,桌子上是否放满了,放满就等待,没放满就接着放,纯粹一点不是更简单吗。

    小朋友拿蛋糕的也是纯粹一些,就看桌子上是否有蛋糕,有就拿,没有就等待。

    1. public class Table {
    2. private int count;//蛋糕的总数
    3. //拿蛋糕 和 放蛋糕 就按顺序来 1 2 3
    4. String[] buffer;
    5. private int tail;//下次 放 的位置
    6. private int head;//下次 拿 的位置
    7. public Table(int count) {
    8. this.buffer = new String[count];
    9. this.count = count;
    10. this.tail = 0;
    11. this.head = 0;
    12. this.count = 0;
    13. }
    14. public synchronized void put(String take) throws InterruptedException {
    15. try {
    16. while (count >= buffer.length) {
    17. wait();
    18. }
    19. } catch (InterruptedException e) {
    20. e.printStackTrace();
    21. }
    22. buffer[tail] = take;
    23. tail = (tail + 1) % buffer.length;
    24. count++;
    25. notifyAll();
    26. System.out.println(Thread.currentThread().getName() + " put() " + take);
    27. }
    28. public synchronized String take() throws InterruptedException {
    29. try {
    30. while (count <= 0) {
    31. wait();
    32. }
    33. } catch (InterruptedException e) {
    34. e.printStackTrace();
    35. }
    36. String take = buffer[head];
    37. head = (head + 1) % buffer.length;
    38. count--;
    39. notifyAll();
    40. System.out.println(Thread.currentThread().getName() + " take() " + take);
    41. return take;
    42. }
    43. }
    1. public class MakerThread extends Thread {
    2. private final Table table;
    3. private static int number = 0;
    4. public MakerThread(String name, Table table) {
    5. super(name);
    6. this.table = table;
    7. }
    8. @Override
    9. public void run() {
    10. super.run();
    11. while (true) {
    12. try {
    13. Thread.sleep(2000);
    14. table.put(number++ + "");
    15. } catch (InterruptedException e) {
    16. e.printStackTrace();
    17. }
    18. }
    19. }
    20. }
    1. public class EaterThread extends Thread {
    2. private final Table table;
    3. public EaterThread(String name, Table table) {
    4. super(name);
    5. this.table = table;
    6. }
    7. @Override
    8. public void run() {
    9. super.run();
    10. while (true) {
    11. try {
    12. Thread.sleep(5000);
    13. table.take();
    14. } catch (InterruptedException e) {
    15. e.printStackTrace();
    16. }
    17. }
    18. }
    19. }
    1. public class Main {
    2. public static void main(String[] args) {
    3. Table table = new Table(5);
    4. MakerThread makerThread1 = new MakerThread("MakerThread1", table);
    5. MakerThread makerThread2 = new MakerThread("MakerThread2", table);
    6. makerThread1.start();
    7. makerThread2.start();
    8. EaterThread eaterThread1 = new EaterThread("EaterThread1", table);
    9. EaterThread eaterThread2 = new EaterThread("EaterThread2", table);
    10. EaterThread eaterThread3 = new EaterThread("EaterThread3", table);
    11. EaterThread eaterThread4 = new EaterThread("EaterThread4", table);
    12. EaterThread eaterThread5 = new EaterThread("EaterThread5", table);
    13. eaterThread1.start();
    14. eaterThread2.start();
    15. eaterThread3.start();
    16. eaterThread4.start();
    17. eaterThread5.start();
    18. }
    19. }

    image.png