java多线程-阻塞队列BlockingQueue
大纲
- BlockingQueue接口
- ArrayBlockingQueue
一、BlockingQueue接口
public interface BlockingQueue<E> extends Queue<E> {
//add、offer向队列插值,返回插入是否成功
boolean add(E e);
boolean offer(E e);
//向队列插值,队列满则阻塞至队列非满
void put(E e) throws InterruptedException;
//offer方法加上超时,超时返回false
boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;
//从队列拿值,队列空则阻塞至队列非空
E take() throws InterruptedException;
//向队列拿值,返回是否成功,超时返回false
E poll(long timeout, TimeUnit unit) throws InterruptedException;
//队列剩余空间
int remainingCapacity();
//删除
boolean remove(Object o);
//是否包含
boolean contains(Object o);
//移除队列中的值到集合中
int drainTo(Collection<? super E> c);
//maxElements移除最大个数
int drainTo(Collection<? super E> c, int maxElements);
}
二、ArrayBlockingQueue
主要成员变量
/** 队列 */
final Object[] items; /** 拿值的索引,用于 take, poll, peek, remove 方法*/
int takeIndex; /** 存值的索引, 用于 next put, offer, or, add 方法*/
int putIndex; /** 队列中元素数量 */
int count; /** 锁,两个condition都是由这个锁创建 */
final ReentrantLock lock; /** 可以拿值的Condition(不空可拿) */
private final Condition notEmpty; /** 可以存值的Condition(不满可存) */
private final Condition notFull;
构造函数
public ArrayBlockingQueue(int capacity) {
this(capacity, false);
} public ArrayBlockingQueue(int capacity, boolean fair) {
//初始化锁与condition,默认非公平所
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
} public ArrayBlockingQueue(int capacity, boolean fair,
Collection<? extends E> c) {
this(capacity, fair);
//将集合中元素拷贝至队列
final ReentrantLock lock = this.lock;
lock.lock(); // Lock only for visibility, not mutual exclusion
try {
int i = 0;
try {
for (E e : c) {
checkNotNull(e);
items[i++] = e;
}
} catch (ArrayIndexOutOfBoundsException ex) {
throw new IllegalArgumentException();
}
//队列数量等于集合数量
count = i;
//存索引赋值:队列满赋0,不满赋集合数量
putIndex = (i == capacity) ? 0 : i;
} finally {
lock.unlock();
}
}
主要方法
取:
//非阻塞
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return (count == 0) ? null : dequeue();
} finally {
lock.unlock();
}
} //阻塞
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
//队列大小为0拿值线程阻塞
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}
//出队
private E dequeue() {
final Object[] items = this.items;
E x = (E) items[takeIndex];
items[takeIndex] = null;
//对应putindex
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
//唤醒存值线程
notFull.signal();
return x;
}
存:
//入队
private void enqueue(E x) {
// assert lock.getHoldCount() == 1;
// assert items[putIndex] == null;
final Object[] items = this.items;
items[putIndex] = x;
if (++putIndex == items.length)
putIndex = 0;
count++;
notEmpty.signal();
}
//非阻塞
public boolean offer(E e) {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count == items.length)
return false;
else {
enqueue(e);
return true;
}
} finally {
lock.unlock();
}
}
//阻塞
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
//队列满则阻塞
while (count == items.length)
notFull.await();
enqueue(e);
} finally {
lock.unlock();
}
}
阻塞队列阻塞的存取值方法通过2个condition的await和signal方法完成:当队列空时notEmpty.await取值阻塞,当队列满时notFull.await存值阻塞;入队操作完成时调用notEmpty.signal唤醒取值线程,出队才做完成时唤醒存值线程。
java多线程-阻塞队列BlockingQueue的更多相关文章
- Java多线程 阻塞队列和并发集合
转载:大关的博客 Java多线程 阻塞队列和并发集合 本章主要探讨在多线程程序中与集合相关的内容.在多线程程序中,如果使用普通集合往往会造成数据错误,甚至造成程序崩溃.Java为多线程专门提供了特有的 ...
- java 多线程阻塞队列 与 阻塞方法与和非阻塞方法
Queue是什么 队列,是一种数据结构.除了优先级队列和LIFO队列外,队列都是以FIFO(先进先出)的方式对各个元素进行排序的.无论使用哪种排序方式,队列的头都是调用remove()或poll()移 ...
- Java多线程—阻塞队列和生产者-消费者模式
阻塞队列支持生产者-消费者这种设计模式.该模式将“找出需要完成的工作”与“执行工作”这两个过程分离开来,并把工作项放入一个“待完成“列表中以便在随后处理,而不是找出后立即处理.生产者-消费者模式能简化 ...
- Java并发编程-阻塞队列(BlockingQueue)的实现原理
背景:总结JUC下面的阻塞队列的实现,很方便写生产者消费者模式. 常用操作方法 常用的实现类 ArrayBlockingQueue DelayQueue LinkedBlockingQueue Pri ...
- Java并发(十八):阻塞队列BlockingQueue
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列. 这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用. 阻塞队列常用于生产 ...
- Java并发指南11:解读 Java 阻塞队列 BlockingQueue
解读 Java 并发队列 BlockingQueue 转自:https://javadoop.com/post/java-concurrent-queue 最近得空,想写篇文章好好说说 java 线程 ...
- Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例
Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例 本文由 TonySpark 翻译自 Javarevisited.转载请参见文章末尾的要求. Java.util.concurr ...
- spring线程池ThreadPoolTaskExecutor与阻塞队列BlockingQueue
一: ThreadPoolTaskExecutor是一个spring的线程池技术,查看代码可以看到这样一个字段: private ThreadPoolExecutor threadPoolExecut ...
- java并发阻塞队列
Java 并发编程利用 Condition 来实现阻塞队列 You are here: 开发&语言 - Java 文章 发布于 2017年06月26日 阅读 944 并发编程 什么是阻 ...
随机推荐
- dd命令使用
一.dd命令的解释 dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换. 注意:指定数字的地方若以下列字符结尾,则乘以相应的数字:b=512:c=1:k=1024:w=2 参数注释: 1. ...
- CodeForces 288A Polo the Penguin and Strings (水题)
题意:给定一个字符,让你用前 k 个字符把它排成 n 长度,相邻的字符不能相等,并且把字典序最小. 析:其实很简单么,我们只要多循环ab,就行,最后再把剩下的放上,要注意k为1的时候. 代码如下: # ...
- Cannot change version of project facet Dynamic Web Module to 2.4.
解决办法,找到项目目录,将.settings target .classpath .project 删除 重新引入项目 原因是 web.xml 文件里<web-app 里的与.settin ...
- 编写高质量代码改善C#程序的157个建议——建议103:区分组合和继承的应用场合
建议103:区分组合和继承的应用场合 继承所带来的多态性虽然是面向对象的一个重要特性,但这种特性不能在所有的场合中滥用.继承应该被当做设计架构的有用补充,而不是全部. 组合不能用于多态,但组合使用的频 ...
- java 访问HTTPS rest服务
import java.io.*;import java.net.*;import java.security.cert.CertificateException;import java.securi ...
- 设计模式11---组合模式(Composite Pattern)
一.组合模式定义 将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性.Compose objects into tree structures to re ...
- 基于Qt5 跨平台应用开发
1.Qt简介 2.Qt 编程关键技术 2.1 信号与槽 2.2 Qt事件处理 3.Qt开发与实例分析 3.1 开发环境 3.2 系统实现基本框架 3.3 数据库管理 3.5 对Excel进行操作 4. ...
- 关于super关键字与继承
super它只是一个限定词,当用super引用时,它也是引用当前对象本身,只是super只是限定了访问当前对象从父类那里继承得到成员变量或方法. import java.util.Date; publ ...
- Android-ListView-SimpleAdapter
我在上一篇博客中Android-动态添加控件到ScrollView,写到可以用Java动态添加控件到Scrollview的孩子LinearLayout里面去,这种方式是不合理的,因为这种方式是一次性把 ...
- Verilog MIPS32 CPU(八)-- 控制器
Verilog MIPS32 CPU(一)-- PC寄存器 Verilog MIPS32 CPU(二)-- Regfiles Verilog MIPS32 CPU(三)-- ALU Verilog M ...