• 多线程生产者消费者案例


    题目需求:写一个生产者消费者容器,支持多个生产者消费者同时访问,容器里最多放十个数,需要get()和put()方法,当容器中没数据时,生产者开始生产数据,消费者等待,数据量满十个时,生产者等待,消费者开始消费.

    /**
     * Created by canner on 2018/11/30.
     */
    public class MyContainer<T> {
    
        private final int MAX = 10;
    
        private final LinkedList<T> list = new LinkedList<>();
    
        private int count = 0;
    
       private Lock lock = new ReentrantLock();
       private Condition producer = lock.newCondition();
       private Condition consumer = lock.newCondition();
    
       public void put(T t){
           try {
    // 拿到当前对象的锁,锁定对象 lock.lock();
    while(list.size() == MAX){ try { producer.await(); } catch (InterruptedException e) { e.printStackTrace(); } } list.add(t); ++ count;       // 唤醒所有消费者 consumer.signalAll(); } finally {
           // 释放锁 lock.unlock(); } }
    public T get(){ try {
           // 拿到当前对象的锁 lock.lock();
    // 当容器数量为0时,消费者等待
    while (list.size() == 0){ try { consumer.await(); } catch (InterruptedException e) { e.printStackTrace(); } } T t = list.removeFirst(); count -- ;
          // 唤醒所有生产者 producer.signalAll();
    return t; } finally { lock.unlock(); } } public static void main(String[] args) { final MyContainer<String> contaional = new MyContainer<>(); for (int i = 0; i < 2; i++) { new Thread(new Runnable() { @Override public void run() { while (true){ contaional.put("线程:"+Thread.currentThread().getName()+" 生产数据"); System.out.println(String.format("往容器放数据-->线程名[%s]",Thread.currentThread().getName())); } } }, "p" + i).start(); } for (int i = 0; i < 5; i++) { new Thread(new Runnable() { @Override public void run() { while (true){ System.out.println("消费" + contaional.get()); } } }, "c"+i).start(); } } }

    本题的坑:①:一定要选同while,因为当容器满了的时候,会唤醒消费者消费,消费者消费了一个会signalAll()所有生产者,所以存在当生产者A拿到锁生产之后,生产者B接着拿到了这把锁,由于没有用while做二次判断,所以接着往下执行,容器的最大数量就超过10了.
         ②:一定要用sinalAll()而不是sinal(),必须唤醒所有的线程,只唤醒一个线程的时候程序有可能造成所有线程都在await()状态.
    本题选用sychronized使用wait()和notifyAll()是相同的做法,只是用Lock加Conditon的优势在于能选定唤醒哪种类型的线程.
  • 相关阅读:
    pytest扫盲21--pytest-assume多重效验插件
    pytest扫盲20--HTML报告
    pytest扫盲19--pytest重运行机制
    pytest扫盲18--配置文件pytest.ini
    pytest扫盲17--自定义命令行参数
    pytest扫盲16--某个用例失败后,关联的用例标记为xfail
    pytest扫盲15--skip跳过用例
    pytest扫盲14--pytest.raises()函数文档及在参数化中处理异常
    pytest扫盲13--遇到异常的两种处理方式及断言异常
    【CF】CF1430_G Yet Another DAG Problem_最小割/网络流/状压dp
  • 原文地址:https://www.cnblogs.com/icanner/p/10043977.html
Copyright © 2020-2023  润新知