多线程生产者消费者案例
Posted icanner
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程生产者消费者案例相关的知识,希望对你有一定的参考价值。
题目需求:写一个生产者消费者容器,支持多个生产者消费者同时访问,容器里最多放十个数,需要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的优势在于能选定唤醒哪种类型的线程.
以上是关于多线程生产者消费者案例的主要内容,如果未能解决你的问题,请参考以下文章