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 ...
随机推荐
- Eclipse安装Activiti插件(流程设计器)
Eclipse安装Activiti插件(流程设计器) 一.安装步骤: 1,打开Eclipse的 Help -> Install New Software,填上插件地址: Name:Activit ...
- mybatis v jpa
mybatis的优势在于SQL的自由度上,SQL优化和返回对象的大小都是可控的.spring-data-JPA则在开发效率上有优势.
- RocEDU.阅读.写作《苏菲的世界》书摘
我们在成长的过程当中,似乎失去了对这世界的好奇心.也正因此,我们丧失了某种极为重要的能力(这也是一种哲学家们想要使人们恢复的能力).因为,在我们内心的某处,有某个声音告诉我们:生命是一种很庞大的.神秘 ...
- 20145328 《Java程序设计》实验二实验报告
20145328 <Java程序设计>实验二实验报告 实验名称 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 ...
- Seccon2017-pwn500-video_player
感觉这个题目并不值500分,有些地方比较牵强,漏洞也比较明显,解题方法有多种,出题者把堆的布局随机化了,不过使用fastbin doublefree的话,可以完全忽视被打乱的堆. from pwn i ...
- openwrt的编译系统是如何制作根文件系统的
答:分析以下makefile即可获取整个过程 以nxp layerscape系统的编译过程为例 1.分析target/linux/layerscape/image/Makefile的最后一句,这是一个 ...
- 如何将JS里变量的值赋给文本框
举个栗子: <html><HEAD><script type="text/javascript" language="Javascript1 ...
- Codeforces Round #241 (Div. 2) B. Art Union 基础dp
B. Art Union time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
- Spring MVC 方法注解拦截器
应用场景,在方法级别对本次调用进行鉴权,如api接口中有个用户唯一标示accessToken,对于有accessToken的每次请求可以在方法加一个拦截器,获得本次请求的用户,存放到request或者 ...
- pg按日,周,月进行数据统计
pg数据库按周,月统计数据 SELECT date_trunc('WEEK', insert_time) as insertDate, SUM(data_increment) as dataTotal ...