Java -- 使用阻塞队列(BlockingQueue)控制线程通信
BlockingQueeu接口是Queue的子接口,但是它的主要作用并不是作为容器,而是作为线程同步的工具。
特征:
当生产者线程试图向BlockingQueue中放入元素时,如果该队列已满,则该线程被阻塞;当消费者线程试图从BlockingQueue中取出元素时,如果该队列已空,则该线程被阻塞。
程序的两个线程通过交替从BlockingQueue中放入元素、取出元素,即可很好地控制线程的通信。
BlockingQueue提供如下两个支持阻塞的方法:
put(E e):尝试从BlockingQueue的头部取出元素,如果该队列的元素已满,则阻塞该线程。
take():尝试从BlockingQueue的头部取出元素,如果该队列的元素已空,则阻塞该线程。
BlockingQueue继承了Queue接口,当然也可以使用Queue接口的方法。这些方法归纳起来可分为3组:
- 在队列尾部插入元素。包括add(E e)、offer(E e)和put(E e)方法,当该队列已满时,这3个方法分别抛出异常、返回false、阻塞队列。
- 在队列头部删除并返回删除的元素。包括remove()、poll()和take()方法。当该队列已空时,这3个方法分别抛出异常、返回false、阻塞队列。
- 在队列头部取出但是不删除元素。包括element()和peek()方法,当队列已空时,这两个方法分别抛出异常、返回false。
BlockingQueue队列的5个实现类:
- ArrayBlockingQueue:基于数组实现的BlockingQueue队列
- LinkedBlockingQueue:基于链表实现的BlockingQueue队列
- PriorityBlockingQueue:.....
- SynchronousQueue:同步队列。对对垒的存、取操作必须交替进行
- DelayQueue:.....
具体代码示例:
package com.fuchenggang.blockingqueue; import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; /**
* @ClassName: Producer
* @Description: 生产者
* @author fucg@kunyitech.com
* @date 2015年7月10日 下午4:08:03
*/
class Producer extends Thread {
private BlockingQueue<String> bq; public Producer(BlockingQueue<String> bq) {
this.bq = bq;
} @Override
public void run() {
String[] strArr = new String[]
{
"Java",
"Struts",
"Spring"
}; for (int i = 0; i < 999999999; i++) {
System.out.println(getName() + "生产者准备生产集合元素!"); try {
Thread.sleep(200);
//尝试放入元素,如果队列已满,则线程被阻塞
bq.put(strArr[i%3]);
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println(getName() + "生产完成:" +bq);
}
}
} /**
* @ClassName: Consumer
* @Description: 消费者
* @author fucg@kunyitech.com
* @date 2015年7月10日 下午4:08:19
*/
class Consumer extends Thread{ private BlockingQueue<String> bq; public Consumer(BlockingQueue<String> bq) {
this.bq = bq;
} @Override
public void run() {
while (true) {
System.out.println(getName() + "消费者准备消费集合元素"); try {
Thread.sleep(200);
//尝试取出元素,如果队列已空,则线程被阻塞
bq.take();
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println(getName() + "消费完成:" + bq);
}
}
} /**
* @ClassName: BlockingQueueTest2
* @Description: 测试生产者线程和消费者线程的通信
* @author fucg@kunyitech.com
* @date 2015年7月10日 下午4:13:37
*/
public class BlockingQueueTest2 {
public static void main(String[] args) {
//创建一个容器为1的BlockingQueue
BlockingQueue<String> bq = new ArrayBlockingQueue<String>(1); //启动3个生产者线程
new Producer(bq).start();
new Producer(bq).start();
new Producer(bq).start(); //启动1个消费者线程
new Consumer(bq).start();
}
}
代码讲解:
程序启动了3个生产者线程向BolckingQueue集合放入元素,启动了1个消费者线程从BlockingQueue集合中取出元素。本程序的BlockingQueue集合容量为1,因此3个生产者线程无法连续放入元素,必须等待消费者线程取出一个元素后,3个生产者线程之一才能放入一个元素。
运行结果:

Java -- 使用阻塞队列(BlockingQueue)控制线程通信的更多相关文章
- java多线程-阻塞队列BlockingQueue
大纲 BlockingQueue接口 ArrayBlockingQueue 一.BlockingQueue接口 public interface BlockingQueue<E> exte ...
- Java---Condition控制线程通信
java中控制线程通信的方法有:1.传统的方式:利用synchronized关键字来保证同步,结合wait(),notify(),notifyAll()控制线程通信.不灵活. 2.利用Conditio ...
- Java并发编程-阻塞队列(BlockingQueue)的实现原理
背景:总结JUC下面的阻塞队列的实现,很方便写生产者消费者模式. 常用操作方法 常用的实现类 ArrayBlockingQueue DelayQueue LinkedBlockingQueue Pri ...
- Java并发(十八):阻塞队列BlockingQueue
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列. 这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用. 阻塞队列常用于生产 ...
- spring线程池ThreadPoolTaskExecutor与阻塞队列BlockingQueue
一: ThreadPoolTaskExecutor是一个spring的线程池技术,查看代码可以看到这样一个字段: private ThreadPoolExecutor threadPoolExecut ...
- Java并发指南11:解读 Java 阻塞队列 BlockingQueue
解读 Java 并发队列 BlockingQueue 转自:https://javadoop.com/post/java-concurrent-queue 最近得空,想写篇文章好好说说 java 线程 ...
- Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例
Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例 本文由 TonySpark 翻译自 Javarevisited.转载请参见文章末尾的要求. Java.util.concurr ...
- Java集合--阻塞队列及各种实现的解析
阻塞队列(Blocking Queue) 一.队列的定义 说的阻塞队列,就先了解下什么是队列,队列也是一种特殊的线性表结构,在线性表的基础上加了一条限制:那就是一端入队列,一端出队列,且需要遵循FIF ...
- Java多线程 阻塞队列和并发集合
转载:大关的博客 Java多线程 阻塞队列和并发集合 本章主要探讨在多线程程序中与集合相关的内容.在多线程程序中,如果使用普通集合往往会造成数据错误,甚至造成程序崩溃.Java为多线程专门提供了特有的 ...
- Condition控制线程通信
Condition控制线程通信 一.前言 java.util.concurrent.locks.Condition 接口描述了可能会与锁有关联的条件变量.这些变量在用法上与使用Object.wait ...
随机推荐
- python 切换工作路径 为指定文件夹
切换工作路径为了更好的在目录下面执行针对当前项目的命令 比如 git.svn .打包 等操作 关键命令: os.chdir() 切换到指定路径: # sys.path[0] 当前脚本路径 # 当前脚本 ...
- 解决 maven项目在eclipse中debug时看不到源码问题
第一步: 第二步:Configurations 里面的source里面是Default.把Defaul删除,选java project ,然后添加自己的项目 第三步:选中,并用命令跑tomcat 这样 ...
- 单调队列:temperature
题目大意:某国进行了连续n天的温度测量,测量存在误差,测量结果是第i天温度在[l_i,r_i]范围内. 求最长的连续的一段,满足该段内可能温度不降. 第一行n下面n行,每行l_i,r_i 1<= ...
- PHP中的strtotime()函数
参见: http://www.phppan.com/2011/06/php-strtotime/ http://developer.51cto.com/art/201107/275478.htm PH ...
- Java 线程池Future和FutureTask
Future表示一个任务的周期,并提供了相应的方法来判断是否已经完成或者取消,以及获取任务的结果和取消任务. Future接口源码: public interface Future<V> ...
- poj3299 - Humidex
2017-08-31 19:08:25 writer:pprp 水题: 没有技术含量hhh 但是,还是花了很长时间,以后水题也是很有必要练习的 /* @theme:poj 3299 @writer:p ...
- Python学习札记(十九) 高级特性5 迭代器
参考:迭代器 Note 1.可用于for循环的对象有两类:(1)集合数据类型:list tuple dict str set (2)Generator:生成器和含yield语句的函数.这些可以直接作用 ...
- 对spring boot 之AutoConfiguration 的理解
来自:http://rensanning.iteye.com/blog/2363467 https://blog.csdn.net/tincox/article/details/79186067 Au ...
- R中的sub替换函数【转】
R中的grep.grepl.sub.gsub.regexpr.gregexpr等函数都使用正则表达式的规则进行匹配.默认是egrep的规则,也可以选用Perl语言的规则.在这里,我们以R中的sub函数 ...
- Eclipse 中从SVN下载的项目如何解除关联上传到另一SVN路径下
首先选中项目右击-->team-->断开连接 选择第一个即可断开与上一个SVN关联 然后上传到另一SVN路径下 选中项目右击-->team-->Share Project ...