分享

java并发(十九)阻塞队列

 roydocs 2015-04-15
阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素。同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,如从队列中移除一个或者多个元素,或者完全清空队列,下图展示了如何通过阻塞队列来合作:





线程1往阻塞队列中添加元素,而线程2从阻塞队列中移除元素



从5.0开始,JDK在java.util.concurrent包里提供了阻塞队列的官方实现。尽管JDK中已经包含了阻塞队列的官方实现,但是熟悉其背后的原理还是很有帮助的。



java之中的BlockingQueue

先进先出。相对的,栈是后进先出。



BlockingQueue,“阻塞队列”:可以提供阻塞功能的队列。

BlockingQueue提供的常用方法:

       可能报异常 返回布尔值 可能阻塞      设定等待时间

入队 add(e)         offer(e)    put(e) offer(e, timeout, unit)

出队 remove()      poll()      take() poll(timeout, unit)

查看 element()      peek()      无 无



add(e) remove() element() 方法不会阻塞线程。当不满足约束条件时,会抛出IllegalStateException 异常。例如:当队列被元素填满后,再调用add(e),则会抛出异常。

offer(e) poll() peek() 方法即不会阻塞线程,也不会抛出异常。例如:当队列被元素填满后,再调用offer(e),则不会插入元素,函数返回false。

要想要实现阻塞功能,需要调用put(e) take() 方法。当不满足约束条件时,会阻塞线程。



阻塞队列的实现

阻塞队列的实现类似于带上限的Semaphore的实现。下面是阻塞队列的一个简单实现

Java代码 复制代码 收藏代码
  1. import java.util.LinkedList;  
  2. import java.util.List;  
  3.   
  4. public class BlockingQueue {  
  5.     private List<Object> queue = new LinkedList<Object>();  
  6.     private int limit = 10;  
  7.   
  8.     public BlockingQueue(int limit) {  
  9.         this.limit = limit;  
  10.     }  
  11.   
  12.     public synchronized void enqueue(Object item) throws InterruptedException {  
  13.         while (this.queue.size() == this.limit) {  
  14.             wait();  
  15.         }  
  16.         if (this.queue.size() == 0) {  
  17.             notifyAll();  
  18.         }  
  19.         this.queue.add(item);  
  20.     }  
  21.   
  22.     public synchronized Object dequeue() throws InterruptedException {  
  23.         while (this.queue.size() == 0) {  
  24.             wait();  
  25.         }  
  26.         if (this.queue.size() == this.limit) {  
  27.             notifyAll();  
  28.         }  
  29.         return this.queue.remove(0);  
  30.     }  
  31. }  


必须注意到,在enqueue和dequeue方法内部,只有队列的大小等于上限(limit)或者下限(0)时,才调用notifyAll方法。如果队列的大小既不等于上限,也不等于下限,任何线程调用enqueue或者dequeue方法时,都不会阻塞,都能够正常的往队列中添加或者移除元素。
 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多