java生产者消费者 阻塞_java之使用阻塞队列实现生产者,消费者模式

在看代码之前,笔者先说几句题外话,生产者-消费者模式,一直是多线程编程中的经典设计模式,不仅仅提现在Java中,各个类C语言,以及其他的一些高级语言中都有实现,在Java 5之前,还没有出现阻塞队列的容器时,实现一个生产者消费者模式,相对来说比较复杂,代码量也比较大,最重要的是设计同步存取时更需要小心谨慎,一不小心就会带来莫名其妙的问题。

Java 5之前实现同步存取时,可以使用普通的一个集合,然后在使用线程的协作和线程同步可以实现生产者,消费者模式,主要的技术就是用好,wait ,notify,notifyAll,sychronized这些关键字。而在java 5之后,可以使用组阻塞队列来实现,此方式大大简少了代码量,使得多线程编程更加容易,安全方面也有保障。

BlockingQueue接口是Queue的子接口,它的主要用途并不是作为容器,而是作为线程同步的的工具,因此他具有一个很明显的特性,当生产者线程试图向BlockingQueue放入元素时,如果队列已满,则线程被阻塞,当消费者线程试图从中取出一个元素时,如果队列为空,则该线程会被阻塞,正是因为它所具有这个特性,所以在程序中多个线程交替向BlockingQueue中放入元素,取出元素,它可以很好的控制线程之间的通信。

下面给出代码实现

package com.queue;

import java.util.concurrent.BlockingQueue;

/***

* 消费者

* **/

public class Consumer extends Thread {

/***

* 利用队列存储样品

* */

private BlockingQueue bq;

public Consumer() {

// TODO Auto-generated constructor stub

}

public Consumer(BlockingQueue bq) {

super();

this.bq = bq;

}

@Override

public void run() {

while(true){

System.out.println(getName()+"消费者准备消费集合元素");

try{

Thread.sleep(2000);

//尝试取出元素,如果队列为空,则被线程阻塞

bq.take();

}catch(Exception e){

e.printStackTrace();

}

System.out.println(getName()+"消费完成"+bq);

}

}

}

package com.queue;

import java.util.concurrent.BlockingQueue;

/**

* 生产者

* **/

public class Producer extends Thread{

/***

* 利用队列存储样品

* */

private BlockingQueue bq;

public Producer() {

// TODO Auto-generated constructor stub

}

public Producer(BlockingQueue bq) {

this.bq = bq;

}

@Override

public void run() {

String []str=new String[]{"solr","lucene","nutch"};

for(int i=0;i<99999999;i++){

System.out.println(getName()+"生产者准备生产集合元素了!");

try{

Thread.sleep(2000);

//尝试放入元素,如果对列已满,则线程被阻塞

bq.put(str[i%3]);

}catch(Exception e){

e.printStackTrace();

}

System.out.println(getName()+"生产完成:"+bq);

}

}

}

package com.queue;

import java.util.concurrent.ArrayBlockingQueue;

import java.util.concurrent.BlockingQueue;

/**

* 生产者,消费者测试

*

* **/

public class BlockingQueueTest {

public static void main(String[] args) {

//创建一个容量为1的队列

BlockingQueue bq=new ArrayBlockingQueue<>(1);

//启动三个生产者线程

new Producer(bq).start();

new Producer(bq).start();

new Producer(bq).start();

//启动一个消费者线程

new Consumer(bq).start();

}

}

Thread-0生产者准备生产集合元素了!

Thread-1生产者准备生产集合元素了!

Thread-2生产者准备生产集合元素了!

Thread-3消费者准备消费集合元素

Thread-0生产完成:[solr]

Thread-0生产者准备生产集合元素了!

Thread-3消费完成[]

Thread-3消费者准备消费集合元素

Thread-1生产完成:[solr]

Thread-1生产者准备生产集合元素了!

Thread-3消费完成[solr]

Thread-2生产完成:[solr]

Thread-2生产者准备生产集合元素了!

Thread-3消费者准备消费集合元素

Thread-3消费完成[lucene]

Thread-3消费者准备消费集合元素

Thread-0生产完成:[lucene]

Thread-0生产者准备生产集合元素了!

总之,利用好队列就可以用很少的代码量实现一个稳定,高效生产者,消费者模式,

966903dea4bcb507358d5dcce8b912e5.gif

分享到:

18e900b8666ce6f233d25ec02f95ee59.png

72dd548719f0ace4d5f9bca64e1d7715.png

2013-07-22 12:14

浏览 5956

评论

1 楼

taoshi

2014-11-25

谢谢您分享.

966903dea4bcb507358d5dcce8b912e5.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值