多线程生产者消费者案例

题目需求:写一个生产者消费者容器,支持多个生产者消费者同时访问,容器里最多放十个数,需要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的优势在于能选定唤醒哪种类型的线程.

转载于:https://www.cnblogs.com/icanner/p/10043977.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值