image.png

    根据上图,可以分析出需求:

    • 生产者和消费者共享一个缓存区,缓存区的最大容量为N
    • 生产者负责生产产品,并放入缓存区中;消费者负责消费产品,从缓存区中取出产品
    • 当缓存区满的时候,不能再放入缓存区,生产者需要阻塞等待
    • 当缓存区为空的时候,不能再取出产品,消费者要阻塞等待
    • 生产者和消费者进程对缓存区的访问是互斥的

    使用Java代码,创建线程并使用锁完成上述需求:

    1. /**
    2. * Created By IntelliJ IDEA
    3. *
    4. * @author IceCreamQAQ
    5. * @datetime 2022/10/20 星期四
    6. * Happy Every Coding Time~
    7. */
    8. public class Producer extends Thread{
    9. public static final Log log = LogFactory.get(Producer.class);
    10. private final MyData myData;
    11. private String name;
    12. public Producer(MyData myData, String name) {
    13. this.myData = myData;
    14. this.name = "生产者" + name + "号";
    15. }
    16. @Override
    17. public void run() {
    18. while(true) {
    19. synchronized (myData) {
    20. log.info(this.name + "获取到锁");
    21. if(myData.getCount() == myData.getMaxNum()) {
    22. // 获取当前时间
    23. log.info(this.name + "已达到最大值,等待消费");
    24. try {
    25. myData.wait();
    26. } catch (InterruptedException e) {
    27. throw new RuntimeException(e);
    28. }
    29. }
    30. myData.setCount(myData.getCount() + 1);
    31. log.info(this.name + "生产一个产品,当前产品个数:" + myData.getCount());
    32. if(myData.getCount() == 1) {
    33. myData.notify();
    34. }
    35. try {
    36. Thread.sleep(500);
    37. } catch (InterruptedException e) {
    38. throw new RuntimeException(e);
    39. }
    40. }
    41. }
    42. }
    43. }
    1. /**
    2. * Created By IntelliJ IDEA
    3. *
    4. * @author IceCreamQAQ
    5. * @datetime 2022/10/20 星期四
    6. * Happy Every Coding Time~
    7. */
    8. public class Consumer extends Thread{
    9. public static final Log log = LogFactory.get(Consumer.class);
    10. private final MyData myData;
    11. private String name;
    12. public Consumer(MyData myData, String name) {
    13. this.myData = myData;
    14. this.name = "消费者" + name + "号";
    15. }
    16. @Override
    17. public void run() {
    18. while(true) {
    19. synchronized (myData) {
    20. log.info(this.name + "获取到锁");
    21. if (myData.getCount() == 0) {
    22. log.info(this.name + "已经消费完毕,等待生产");
    23. try {
    24. myData.wait();
    25. } catch (InterruptedException e) {
    26. throw new RuntimeException(e);
    27. }
    28. }
    29. myData.setCount(myData.getCount() - 1);
    30. log.info(this.name + "消费一个产品,当前产品个数:" + myData.getCount());
    31. if(myData.getCount() == myData.getMaxNum() - 1) {
    32. myData.notify();
    33. }
    34. try {
    35. Thread.sleep(1000);
    36. } catch (InterruptedException e) {
    37. throw new RuntimeException(e);
    38. }
    39. }
    40. }
    41. }
    42. }
    1. /**
    2. * Created By IntelliJ IDEA
    3. *
    4. * @author IceCreamQAQ
    5. * @datetime 2022/10/20 星期四
    6. * Happy Every Coding Time~
    7. */
    8. @Data
    9. @AllArgsConstructor
    10. @NoArgsConstructor
    11. public class MyData {
    12. private int maxNum;
    13. private int count;
    14. }
    1. /**
    2. * Created By IntelliJ IDEA
    3. *
    4. * @author IceCreamQAQ
    5. * @datetime 2022/10/20 星期四
    6. * Happy Every Coding Time~
    7. */
    8. public class Main {
    9. public static void main(String[] args) {
    10. int maxNum = 10;
    11. int count = 0;
    12. MyData myData = new MyData(maxNum, count);
    13. for(int i = 1;i <= 10;i++) {
    14. Producer producer = new Producer(myData, i + "");
    15. producer.start();
    16. }
    17. for(int i = 1;i <= 10;i++) {
    18. Consumer consumer = new Consumer(myData, i + "");
    19. consumer.start();
    20. }
    21. }
    22. }

    测试结果:
    image.png

    会发现中间有一段很奇怪:
    image.png