Java 生产者和消费者模型

生产者和消费者模型

  • 生产线程负责生产,消费线程负责消费
  • 生产和消费要达到平衡

这是一种特殊的业务需求,在这种特殊情况下需要使用基于线程共享对象的wait和notify方法

  1. wait和notify是普通java对象的方法,而不是Runnable实例对象和Thread对象的方法
  2. wait和notify方法都建立在synchronized,因为多线程操作同一个共享对象,存在线程安全问题

模型假设:

  • 假设有一个容量为1的List仓库被一个生产者线程和一个消费者线程共享
  • 生产者不断生产,每次生产一个放到仓库中
  • 消费者不断消费,每次从仓库中取出后消费一个
  • 仓库满的话生产者停止生产,仓库空了的话消费者停止消费

模型示意图:

在这里插入图片描述

模型流程图:

在这里插入图片描述

实现:

主线程:

import java.util.ArrayList;
import java.util.List;

public class ProducerAndConsumer {
    
    
    public static void main(String[] args) {
    
    
        // 创建一个共享的仓库
        List list = new ArrayList();
        // 创建一个生者线程
        Thread proThread = new Thread(new Producer(list));
        //创建一个消费线程
        Thread conThread  = new Thread(new Consumer(list));
        proThread.setName("生产线程");
        conThread.setName("消费线程");
        proThread.start();
        conThread.start();
    }
}

生产者线程:

class Producer extends Thread{
    
    
    /**
     * 共享的那个仓库
     */
    private List list;
    public Producer(List list){
    
    
        this.list = list;
    }

    @Override
    public void run() {
    
    
        //一直生产
        while(true){
    
    
            // 生产得加锁(生产的时候不能消费)
            synchronized (list){
    
    
                // 如果仓库满了,当前线程进入等待状态,并释放对象锁。
                if (list.size()>0){
    
    
                    try {
    
    
                        list.wait();
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                }
                // 能到这说明仓库是空的,可以生产
                Object product = new Object();
                list.add(product);
                System.out.println(Thread.currentThread().getName()+" 生产了:一个产品"+product);
                //生产完了就应该唤醒消费者去消费
                list.notify();
            }
        }
    }
}

消费者线程:

class Consumer extends Thread{
    
    
    private List list;

    public Consumer(List list){
    
    
        this.list = list;
    }

    @Override
    public void run() {
    
    
        //一直消费
        while(true){
    
    
            synchronized (list){
    
    
                // 如果仓库空了就不能消费了,等待生产,
                if (list.size()==0){
    
    
                    try {
    
    
                        list.wait();
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                }
                // 仓库中有东西,消费
                Object product = list.remove(0);
                System.out.println(Thread.currentThread().getName()+" 消费了:一个产品"+product);
                // 消费完了九唤醒生产者去生产
                list.notify();
            }
        }
    }
}

执行结果:

生产线程 生产了:一个产品java.lang.Object@2ea567fa
消费线程 消费了:一个产品java.lang.Object@2ea567fa
生产线程 生产了:一个产品java.lang.Object@2d36607d
消费线程 消费了:一个产品java.lang.Object@2d36607d
生产线程 生产了:一个产品java.lang.Object@26e6a4a8
消费线程 消费了:一个产品java.lang.Object@26e6a4a8
生产线程 生产了:一个产品java.lang.Object@16be2ec1
消费线程 消费了:一个产品java.lang.Object@16be2ec1
...
...
生产线程 生产了:一个产品java.lang.Object@13a1115b
消费线程 消费了:一个产品java.lang.Object@13a1115b
生产线程 生产了:一个产品java.lang.Object@d0aaeda
消费线程 消费了:一个产品java.lang.Object@d0aaeda
生产线程 生产了:一个产品java.lang.Object@1eda9837
消费线程 消费了:一个产品java.lang.Object@1eda9837
生产线程 生产了:一个产品java.lang.Object@7975650b
消费线程 消费了:一个产品java.lang.Object@7975650b
...

猜你喜欢

转载自blog.csdn.net/qq_44957186/article/details/108313130
今日推荐