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

使用阻塞队列(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生产者准备生产集合元素
Thread-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.因此三个生产者无法连续放入元素,必须等待消费者取出一个元素之后,生产者之一才能放入一个元素。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值