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 ...
随机推荐
- Linux下mysql允许远程连接怎么设置
1.root用户登录到mysql数据库代码示例:/usr/local/mysql/bin/mysql -u root -p (输入密码进入mysql)2.进入mysql,输入:代码示例:use mys ...
- JavaScript浮点运算,小数点精度
math.js JavaScript浮点运算,小数点精度 // JavaScript Document //数学函数 // 浮点数加法运算 function floatAdd(arg1, arg2) ...
- 屏幕变黑白-winhotkey
下载了个windows hot key 的工具想看快捷键冲突 结果安装好之后屏幕变黑白了,变成辅助模式了.而且鼠标移动到哪都加蓝色框框 如果这个时候你带上耳机就能听到在朗读,这应该也是一种辅助模式 ...
- ubuntu下 gedit中文乱码
Gedit 3.x 版本设置 (适用于Ubuntu 11.10及以后) 命令方式 gsettings set org.gnome.gedit.preferences.encodings auto-de ...
- (转)C#调用C函数(DLL)传递参数问题
备忘: 1.C函数参数为字符串char*.如果是入参,对应C#中string或StringBuilder:如果是出参对应C#中StringBuider: 2.C函数参数为结构体指针,需在C#中对应定义 ...
- JAVA国际化输出日期格式
1.建议控制台程序 使用 IntelliJ IDEA 创建 MAVEN项目, 不选别的选项,则为控制台程序. (其它方式创建的控制台程序可能编译不过) 2.源码如下: import java.tim ...
- 解析TCP三次握手
转自:http://www.jellythink.com/archives/705 三次握手又是什么? TCP是面向连接的,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接.在TCP/I ...
- docker shipyard 问题
安装 docker shipyard curl -s https://shipyard-project.com/deploy | bash -s docker machine 创建的虚拟机无法直接运 ...
- 《Django By Example》
<Django By Example>第六章 中文 翻译 (个人学习,渣翻) 书籍出处:https://www.packtpub.com/web-development/django-ex ...
- MySQL-性能优化-优化设计和设计原则
MySQL性能优化目的如何合理的设计数据库?什么样的数据库设计才能给后期DBA优化提供基石? 数据库设计与程序设计的差异? 数据库设计早期优化1. 关系明确(理清表之间的关系,可以通过冗余的方式提高效 ...