生产者消费者问题简单解决之ArrayBlockingQueue的详解与使用
来源:互联网 发布:手机视频软件baidu 编辑:程序博客网 时间:2024/06/05 17:52
ArrayBlockingQueue是一个边界缓冲对流,底层是array,他是FIFO先进先出的。新插入的数据会被插入到队列的末尾,而且总是从队头取数据。
生产者把数据插入的队列的末尾,消费者总是从队列的头部拿数据,当队列满了之后,再往队列中插入数据会造成队列的阻塞,同样,从空的队列中取数据,也是阻塞的。
有一个公平策略,我们如果希望,队列中的数据总是按照生产者生产数据的顺序,取队列中的数据,那么我们可以在构造函数中把fair参数设置为true就可以了,但是这种操作会降低吞吐量。
java.lang.Object---java.util.AbstractCollection<E>----java.util.AbstractQueue<E>------java.util.concurrent.ArrayBlockingQueue<E>
从ArrayBlockingQueue的继承体系中我们可以看出,他是属于Collection集合体系的,因此它具有collection和Iterator体系的一系列方法。
对于Collection集合体系的类,方法无非就是,add、put、take、peek、poll、clear等。
具体方法描述详见API
对于生产者消费者问题,会涉及多线程的同步问题,那ArrayBlockingQueue是如何解决多线程同步的问题呢?生产者和消费者共同使用同一个ArrayBlockingQueue,也就是同一个消息队列。生产者往队列的队尾放入数据,消费者从对头拉取数据。那多个生产者和多个消费者如果保证线程同步问题呢,
源码这边,我们来看一个生产者生产的问题:
public void put(E e) throws InterruptedException { checkNotNull(e); final ReentrantLock lock = this.lock;//获取当前锁 lock.lockInterruptibly();//加锁,消费者无法操作queue try { while (count == items.length) notFull.await(); enqueue(e);//入队列 } finally { lock.unlock();//生产者,插入队列结束,释放锁 } }
同样,消费者,消费的时候
public E poll(long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock;//获取当前锁 lock.lockInterruptibly();//加锁,生产者无法操作queue try { while (count == 0) { if (nanos <= 0) return null; nanos = notEmpty.awaitNanos(nanos); } return dequeue();//出队列 } finally { lock.unlock();//消费者,拉取队列数据结束,释放锁 } }
最后一个完整的demo,简单的生产者消费者问题:
import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.TimeUnit;public class ProduceConsumeDemo { public static void main(String[] args) { ArrayBlockingQueue<Cookie> arrayBlockingQueue= new ArrayBlockingQueue<Cookie>(10);//生产者和消费者共用这一个队列,队列容量为10 Produce produce = new Produce(arrayBlockingQueue); produce.start(); //一个生产者,5个消费者 new Thread(new Consume(arrayBlockingQueue)).start(); new Thread(new Consume(arrayBlockingQueue)).start(); new Thread(new Consume(arrayBlockingQueue)).start(); new Thread(new Consume(arrayBlockingQueue)).start(); new Thread(new Consume(arrayBlockingQueue)).start(); }}class Produce extends Thread{ private static int i=0; private ArrayBlockingQueue<Cookie> arrayBlockingQueue; public Produce(ArrayBlockingQueue<Cookie> arrayBlockingQueue){ this.arrayBlockingQueue=arrayBlockingQueue; } public void run(){ try { while (i<1000) { arrayBlockingQueue.put(new Cookie("cookie"+i)); if (++i%100==0){//每生产100个,休息10s Thread.sleep(10000); } } }catch (InterruptedException e){ System.out.println("produce queue InterruptedException"); } }}class Consume implements Runnable{ private ArrayBlockingQueue<Cookie> arrayBlockingQueue; public Consume(ArrayBlockingQueue<Cookie> arrayBlockingQueue){ this.arrayBlockingQueue=arrayBlockingQueue; } public void run(){ try{ while (true){ Cookie poll = arrayBlockingQueue.poll(5, TimeUnit.SECONDS);//如果queue为null,那么5秒之后再去队列中取数据 if (poll!=null) System.out.println(Thread.currentThread().getName()+"--consume --"+poll); } }catch (InterruptedException e){ System.out.println("consume queue InterruptedException"); } }}class Cookie{ private String number; public Cookie(String number){ this.number=number; } @Override public String toString() { return number+""; }}
阅读全文
0 0
- 生产者消费者问题简单解决之ArrayBlockingQueue的详解与使用
- 使用互斥锁解决生产者与消费者问题
- java多线程之生产者与消费者问题的简单模拟
- java多线程之生产者与消费者问题的简单模拟
- Java多线程之生产者消费者问题<一>:使用synchronized 关键字解决生产者消费者问题
- Chapter 7 生产者消费者之ArrayBlockingQueue实现
- 基于ArrayBlockingQueue的生产者和消费者
- 生产者消费者模型 ArrayBlockingQueue
- 生产者与消费者的问题
- 多线程解决生产者与消费者问题
- 1,使用信号量解决生产者-消费者问题
- 使用POSIX线程解决“生产者/消费者”问题
- Java多线程之生产者消费者问题<二>:使用重入锁、条件变量优雅地解决生产者消费者问题
- Java多线程之生产者消费者问题<三>:使用阻塞队列更优雅地解决生产者消费者问题
- 简单消费者生产者问题
- 生产者-消费者问题详解
- 生产者-消费者问题详解
- 生产者-消费者问题详解
- 查找数组重复的元素
- 1、测试基础
- 7-15 找完数(20 分)
- org.hibernate.boot.MappingNotFoundException解决方案
- FPGA-Modelsim仿真不出来波形可能的原因
- 生产者消费者问题简单解决之ArrayBlockingQueue的详解与使用
- spring cloud配置注册中心显示服务的ip地址和端口
- BufferStream
- BZOJ 4530: [Bjoi2014]大融合 lct维护子树信息
- 编写选项卡
- 纸牌屋观后感
- 简单排序(mid)
- JAVA判断时间格式为 "YYYY-MM-DD"
- Shell脚本对数据库的操作