多线程生产者消费者案例

题目需求:写一个生产者消费者容器,支持多个生产者消费者同时访问,容器里最多放十个数,需要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

时间: 2024-07-30 09:45:27

多线程生产者消费者案例的相关文章

java多线程 生产者消费者案例-虚假唤醒

package com.java.juc; public class TestProductAndConsumer { public static void main(String[] args) { Clerk clerk = new Clerk(); Produce produce = new Produce(clerk); Consumer consumer = new Consumer(clerk); new Thread(produce, "线程A").start(); ne

Condition线程通信_生产者消费者案例

①Condition 接口描述了可能会与锁有关联的条件变量. 这些变量在用 法上与使用 Object.wait 访问的隐式监视器类似,但提供了更强大的 功能. 需要特别指出的是,单个 Lock 可能与多个 Condition 对象关 联. 为了避免兼容性问题,Condition 方法的名称与对应的 Object 版 本中的不同.② 在 Condition 对象中,与 wait.notify 和 notifyAll 方法对应的分别是 await.signal 和 signalAll.③ Condi

多线程生产者消费者问题处理

一.比较低级的办法是用wait和notify来解决这个问题. 消费者生产者问题: 这个问题是一个多线程同步问题的经典案例,生产者负责生产对象,消费者负责将生成者产生的对象取出,两者不断重复此过程.这过程需要注意几个问题: 不论生产者和消费者有几个,必须保证: 1.生产者每次产出的对象必须不一样,产生的对象有且仅有出现一次: 2.消费者每次取出的对象必须不一样,取出的对象有且仅有出现一次: 3.一定是先产生该对象,然后对象才能被取出,顺序不能乱: 第一种情况:多个生产者轮流负责生产,多个消费者负责

多线程-生产者消费者

正解博客:https://blog.csdn.net/u011863767/article/details/59731447 永远在循环(loop)里调用 wait 和 notify,不是在 If 语句 现在你知道wait应该永远在被synchronized的背景下和那个被多线程共享的对象上调用,下一个一定要记住的问题就是,你应该永远在while循环,而不是if语句中调用wait.因为线程是在某些条件下等待的--在我们的例子里,即"如果缓冲区队列是满的话,那么生产者线程应该等待",你可

多线程生产者/消费者模式实现

参考书籍<java多线程编程核心技术> 都是基于wait/notify实现的 一个生产者和一个消费者:操作值 1 package com.qf.test10.pojo; 2 3 /** 4 * @author qf 5 * @create 2018-09-18 15:59 6 */ 7 public class Entity { 8 public static String value = ""; 9 } 1 package com.qf.test10; 2 3 impor

java多线程 生产者消费者模式

package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static void main(String[] args) { Godown godown = new Godown(50); for (int i = 0; i < 5; i++) { new ProducerThread(i * 10, godown).start(); new ConsumerThre

[多线程] 生产者消费者模型的BOOST实现

说明 如果 使用过程中有BUG 一定要告诉我:在下面留言或者给我邮件(sawpara at 126 dot com) 使用boost::thread库来实现生产者消费者模型中的缓冲区! 仓库内最多可以存放 capacity 个产品. 条件变量 condition_put 标记是否可以往仓库中存放一个产品. 条件变量 condition_get 标记是否可以从仓库中取出一个产品. 互斥量 mutexer 用于保证当前仓库只有一个线程拥有主权. 实现 #include <queue> #inclu

多线程生产者消费者模式

闲着没事,写了个生产者消费者模式玩玩,顺便熟悉下notify的用法. package sync; public class Test { public static void main(String[] args) { Test test = new Test(); Producer producer = test.new Producer(); producer.start(); Consumer consumer = test.new Consumer(); consumer.setName

多线程--生产者/消费者线程模型

//程序演进1 //thread loop,忙等Busy wait //不断的检查是不是该做什么事情了:为了减少CPU占用,sleep睡眠一会 //while (1) //{ // do_something(); // sleep(time); //} //程序演进2 //while (1) //{ // read_form_intput(); // do_something(); //} //程序员演进3,消息模型 //while (waitForMsg) //{ // if (isQuitM