Java:多线程的生产者和消费者问题

237 阅读1分钟

1. 题目

  • 生产者(Producer)将产品给店员(Clerk)

    消费者(Customer)从店员(Clerk)处取走产品

    店员最多拥有20件产品。当拥有20件产品时,如果生产者生产更多产品,店员会制止

    店员如果没有产品,会叫消费者等一下。

2. 分析:

  1. 是否有多线程问题?
    • 是的,生产者线程,消费者线程。
  2. 是否有共享数据?
    • 有的。店员就是共享数据。
  3. 是否需要解决线程安全问题?
    • 需要。通过三种同步机制。
  4. 是否涉及线程通信?
    • 涉及。店员需要通知生产者暂定生产;通知消费者等一下。

3. 代码逻辑

  1. 将店员包装成一个类。其中包含对共享数据的操作和共享数据。
  2. 生产者包装成类,消费者包装成类。在类中使用单列模式对店员类进行调用。

4.代码实现

  • package test1;
    
    /**
     * @Author -..----.--...../-.--..-.-----.-/----.-.....-.--/-.----.-...----/-.-.-...-.--...
     * @Date 2021/10/23 13:02
     */
    class Clerk { // 店员
        private int num;
    
        // 从生产者接受产品
        public synchronized void producerProduct() {
            if (num < 20) {
                num++;
                notify();
                System.out.println(Thread.currentThread().getName() + ":生产第" + num + "个产品");
            } else {
                // 等待
                try {
                    wait();
                } catch (InterruptedException e) {
                    System.out.println(Thread.currentThread().getName() + ":出现问题");
                    e.printStackTrace();
                }
            }
        }
        // 给消费者产品
        public synchronized void customerProduct() {
            if (num > 0) {
                System.out.println(Thread.currentThread().getName() + ":取走第" + num + "个产品");
                num--;
                notify();
            } else {
                // 等待
                try {
                    wait();
                } catch (InterruptedException e) {
                    System.out.println(Thread.currentThread().getName() + ":出现问题");
                    e.printStackTrace();
                }
            }
        }
    }
    
    class Producer implements Runnable { // 生产者
        private Clerk clerk; // 单列模式
    
        // 使用同一个对象
        public Producer(Clerk clerk) {
            this.clerk = clerk;
        }
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + ":开始生产");
            while (true) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
    
                }
                clerk.producerProduct();
            }
        }
    }
    
    class Customer implements Runnable { // 消费者
        private Clerk clerk; // 单列模式
    
        // 使用同一个对象
        public Customer(Clerk clerk) {
            this.clerk = clerk;
        }
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + ":开始消费");
            while (true) {
    
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
    
                }
                clerk.customerProduct();
            }
        }
    }
    
    public class ProductTest {
        public static void main(String[] args) {
            Clerk clerk = new Clerk();
    
            Producer producer = new Producer(clerk);
            Thread pt1 = new Thread(producer);
            pt1.setName("生产者1");
            pt1.start();
    
            Customer customer = new Customer(clerk);
            Thread ct1 = new Thread(customer);
            Thread ct2 = new Thread(customer);
            ct1.setName("消费者1");
            ct2.setName("消费者2");
            ct1.start();
            ct2.start();
        }
    }