BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题。通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利。使用场景。

首先它是一个队列,而一个队列在数据结构中所起的作用大致如下图所示:

通过一个共享的队列,可以使得数据由队列的一端输入,从另外一端输出;在生产者消费者模式中,通过队列的方式可以很方便的实现两者之间的数据共享。强大的BlockingQueue使我们不用关心什么时候需要阻塞线程,什么时候需要唤醒线程。

BlockingQueue的核心方法:

放入数据:

  offer(anObject) 如果BlockingQueue可以容纳,返回为true,否则返回false.

  offer(E o,long timeout,TimeUnit unit),设置等待时间,如果指定时间内,还不能往队列中加入BlockingQueue,则返回失败。

  put(anObject)把anObject加到BlockingQueue中,如果BlockQueue没有空间,则调用此方法的线程被阻断,直到BlockingQueue里面有空间再继续。

获取数据:
  poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,
    取不到时返回null;
  poll(long timeout, TimeUnit unit):从BlockingQueue取出一个队首的对象,如果在指定时间内,
    队列一旦有数据可取,则立即返回队列中的数据。否则知道时间超时还没有数据可取,返回失败。
  take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到
    BlockingQueue有新的数据被加入; 
  drainTo():一次性从BlockingQueue获取所有可用的数据对象(还可以指定获取数据的个数), 
    通过该方法,可以提升获取数据效率;不需要多次分批加锁或释放锁。

测试代码:

package BlockingQueue;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class BlockingQueueTest {
public static void main(String args[]) throws InterruptedException{
BlockingQueue<String> queue = new ArrayBlockingQueue(10); Producer producer1 = new Producer(queue);
Producer producer2 = new Producer(queue);
Producer producer3 = new Producer(queue);
Consumer consumer = new Consumer(queue); ExecutorService service = Executors.newCachedThreadPool(); service.execute(producer1);
service.execute(producer2);
service.execute(producer3);
service.execute(consumer); Thread.sleep(10 * 1000);
producer1.stop();
producer2.stop();
producer3.stop(); Thread.sleep(2000);
// 退出Executor
service.shutdown();
}
}

生产者:

package BlockingQueue;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; public class Producer implements Runnable{ private volatile boolean isRunning = true;
private BlockingQueue<String> queue;
private static AtomicInteger count = new AtomicInteger();
private static final int DEFAULT_RANGE_FOR_SLEEP = 1000; public Producer(BlockingQueue queue){
this.queue = queue;
} public void run(){
String data = null;
Random r = new Random();
System.out.println("启动生产者线程");
try{
while(isRunning){
System.out.println("正在生产数据.....");
Thread.sleep(r.nextInt(DEFAULT_RANGE_FOR_SLEEP)); data = "data:" + count.incrementAndGet();
System.out.println("将数据:" + data + "放入队列...");
if (!queue.offer(data, 2, TimeUnit.SECONDS)) {
System.out.println("放入数据失败:" + data);
}
}
}catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
finally{
System.out.println("退出生产者线程!");
}
} public void stop(){
isRunning = false;
} }

消费者:

package BlockingQueue;

import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit; public class Consumer implements Runnable{
private BlockingQueue<String> queue;
private static final int DEFAULT_RANGE_FOR_SLEEP = 1000; public Consumer(BlockingQueue<String> queue){
this.queue = queue;
} public void run(){
System.out.println("启动消费者线程:");
Random r = new Random();
boolean isRunning = true;
try{
while(isRunning){
System.out.println("正从队列获取数据...");
String data = queue.poll(2,TimeUnit.SECONDS);
if(null != data){
System.out.println("拿到数据:" + data);
System.out.println("正在消费数据:" + data);
Thread.sleep(r.nextInt(DEFAULT_RANGE_FOR_SLEEP));
}else{
isRunning = false;
}
}
}catch(InterruptedException e){
e.printStackTrace();
Thread.currentThread().interrupt();
}finally{
System.out.println("退出消费者线程!");
}
}
}

参考:http://wsmajunfeng.iteye.com/blog/1629354

使用BlockingQueue的生产者消费者模式的更多相关文章

  1. Java多线程15:Queue、BlockingQueue以及利用BlockingQueue实现生产者/消费者模型

    Queue是什么 队列,是一种数据结构.除了优先级队列和LIFO队列外,队列都是以FIFO(先进先出)的方式对各个元素进行排序的.无论使用哪种排序方式,队列的头都是调用remove()或poll()移 ...

  2. Java设计模式—生产者消费者模式(阻塞队列实现)

    生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...

  3. Queue和BlockingQueue的使用以及使用BlockingQueue实现生产者-消费者

    Java提供了两种新的容器类型:Queue和BlockingQueue. Queue用于保存一组等待处理的元素.它提供了几种实现,包括:ConcurrentLinkedQueue,这是一个先进先出的并 ...

  4. Java多线程-----实现生产者消费者模式的几种方式

       1 生产者消费者模式概述 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理 ...

  5. Java并发编程()阻塞队列和生产者-消费者模式

    阻塞队列提供了可阻塞的put和take方法,以及支持定时的offer和poll方法.如果队列已经满了,那么put方法将阻塞直到有空间可用:如果队列为空,那么take方法将会阻塞直到有元素可用.队列可以 ...

  6. Java Thread系列(十)生产者消费者模式

    Java Thread系列(十)生产者消费者模式 生产者消费者问题(producer-consumer problem),是一个多线程同步问题的经典案例.该问题描述了两个共亨固定大小缓冲区的线程-即所 ...

  7. 10 阻塞队列 & 生产者-消费者模式

    原文:http://www.cnblogs.com/dolphin0520/p/3932906.html 在前面我们接触的队列都是非阻塞队列,比如PriorityQueue.LinkedList(Li ...

  8. Java生产者消费者模式

    为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程.在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能 ...

  9. wait、notify应用场景(生产者-消费者模式)

    Java实现生产者消费者的方式有:wait && notify.BlockingQueue.Lock && Condition等 wait.notify注意事项:(1) ...

随机推荐

  1. leetcode 144. Binary Tree Preorder Traversal ----- java

    Given a binary tree, return the preorder traversal of its nodes' values. For example:Given binary tr ...

  2. JavaScript学习记录总结(七)——dom对象应用之用户简单管理

    <!DOCTYPE html><html><head><title>users.html</title> <meta name=&qu ...

  3. Qt_Window@Qt Command Prompt从命令行创建工程

    #include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplicatio ...

  4. Echarts通过Ajax实现动态数据加载

    Echarts(3.x版)官网实例的数据都是静态的,实际使用中往往会要求从服务器端取数据进行动态显示,官网教程里给出的异步数据加载很粗略,下面就以官网最简单的实例为例子,详细演示如下过程:1.客户端通 ...

  5. UDP/TCP通信小记

    TCP 和UDP的区别 TCP是面向连接的; 所谓连接   就是 打开的时候要握手,收发数据的时候要确认(传说中的窗口协议保持滑动过去的窗口都已成功发送,接收方已经成功接收). UDP是无连接的. 所 ...

  6. 发现PDF Transformer+转换的图像字体小了如何处理

    ABBYY PDF Transformer+转换的原始图像字体太小怎么办?为了获得最佳文本识别效果,请用较高的分辨率扫描用极小字体打印的文档,否则很容易在转换识别时出错.下面小编就给大家讲讲该怎么解决 ...

  7. js 动态 activex 组件

    function writeObject(){ var obj = document.getElementById("mydelphi"); if(!obj){ var divob ...

  8. html初学(三)

    <!-- 我就是我,不一样的烟花 piu piu piu 干啥子 如来神掌 -- --- ----- .======. ***********啊啊啊啊啊啊 | INRI | | | | | .= ...

  9. 自媒体时代网络脱口秀节目的“五W”分析——以《罗辑思维》为例

    摘 要:随着互联网的发展,网络媒介生态的变化正在悄然进行.一大批网络自媒体节目<罗辑思维><晓说><凯子曰>等进入大众视线,成为大众关注的新焦点,其中<罗辑思 ...

  10. 修改mysql root 密码

    C:\Program Files\MySQL\MySQL Server 5.6\bin mysqld --skip-grant-tables 开启一新窗口:然后输入mysql -uroot -p up ...