您的位置:首页 > 产品设计 > UI/UE

使用阻塞队列(BlockingQueue)控制线程通信:

2016-09-21 14:05 585 查看
使用阻塞队列(BlockingQueue)控制线程通信:

(1)Java5提供了一个BlockingQueue接口,虽然BlockingQueue也是Queue的子接口,但它的主要用途并不是作为容器,而是作为线程同步的工具类。BlockingQueue具有一个特征:当生产者线程试图向BlockingQueue中放入元素时,如果该队列已满,则该线程被阻塞;当消费者试图从BlockingQueue中取出元素时,如果队列已空,则该线程被阻塞

(2)程序的两个线程通过交替向BlockingQueue中放入元素、取出元素,即可很好的控制线程通信。

(3)BlockingQueue提供如下两个支持阻塞的办法:

put(E e) 尝试把E元素放入BlockingQueue中,如果该队列元素已满,则阻塞该线程。

take() 尝试从BlockingQueue的头部取出元素,如果该队列的元素已空,则阻塞该线程。

(4)BlockingQueue继承了Queue接口,当然也可以使用Queue中的方法:

*在队列尾部插入元素。包括add(E e) offer(E e) put( E e)

*在队列头部删除并且返回删除的元素。包括 remove() poll() take().

*在队列头部取出但不删除元素。包括element()和peek()方法

(5)BlockingQueue包含以下5个实现类:

ArrayBlockingQueue:基于数组实现的BlockingQueue队列

LinkedBlockingQueue:基于链表实现的BlockingQueue队列

PriorityBlockingQueue:

SynchronousQueue:同步队列,该队列的存取操作必须交替进行。

DelayQueue:

以ArrayBlockingQueue为例介绍阻塞队列的用法。

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class BlockingQueueTest{
public static void main(String[] args)   throws Exception {
//定义一个长度为2的阻塞队列
BlockingQueue<String>    bq=new  ArrayBlockingQueue<>(2);
bq.put("java");
bq.put("c++");
bq.put("java");//阻塞线程
}

}


利用BlockingQueue来实现线程通信:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
class Producer  extends  Thread{
private  BlockingQueue<String>  bq;
public  Producer(BlockingQueue<String>   bq){
this.bq=bq;
}

public  void  run(){
String  []  strArr= new  String []{"java","c++","china"};

for (int i = 0; i < 999999999; i++) {
System.out.println(getName()+"生产者准备生产集合元素");
try {
Thread.sleep(200);
//尝试放入元素,如果队列已满,则线程被阻塞
bq.put(strArr [ i  %  3]);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println(getName()+"生产完成"+bq);
}
}
}
class Consumer  extends  Thread{
private  BlockingQueue<String>  bq;
public  Consumer(BlockingQueue<String>   bq){
this.bq=bq;
}

public  void  run(){
while(true){
System.out.println(getName()+"消费者准备消费集合元素");
try {
Thread.sleep(200);
//尝试取出元素,如果队列已空,则线程被阻塞
bq.take();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println(getName()+"消费完成:"+bq);
}
}
}
public class BlockingQueueTest2 {
public static void main(String[] args) {
//创建一个容量为1的BlockingQueue
BlockingQueue<String>    bq  =  new   ArrayBlockingQueue<>(1);

//启动三个生产者线程
new  Producer(bq).start();
new  Producer(bq).start();
new  Producer(bq).start();

//启动一个消费者线程
new  Consumer(bq).start();
}

}


运行结果:

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

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

Threa
b5cf
d-2生产者准备生产集合元素

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

Thread-0生产完成[java]

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

Thread-1生产完成[java]

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

Thread-3消费完成:[java]

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

Thread-2生产完成[java]

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

Thread-3消费完成:[java]

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

Thread-3消费完成:[c++]

Thread-0生产完成[c++]

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

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

Thread-1生产完成[c++]

Thread-3消费完成:[c++]

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

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

上面程序启动了三个生产者线程向BlockingQueue集合放入元素,启动了一个消费者线程从BlockingQueue中取出元素。本程序的集合容量为1.因此三个生产者无法连续放入元素,必须等待消费者取出一个元素之后,生产者之一才能放入一个元素。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: