Blocking Queues

A blocking queue is a queue that blocks when you try to dequeue from it and the queue is empty, or if you try to enqueue items to it and the queue is already full. A thread trying to dequeue from an empty queue is blocked until some other thread inserts an item into the queue. A thread trying to enqueue an item in a full queue is blocked until some other thread makes space in the queue, either by dequeuing one or more items or clearing the queue completely.
阻塞队列是一个队列:
情况1:希望出队,但队为空 【直到其他线程将元素入队,才结束阻塞】
情况2:希望入队,但队为满 【直到其他线程将元素出队,才结束阻塞】

Here is a diagram showing two threads cooperating via a blocking queue:
在这里插入图片描述
A BlockingQueue with one thread putting into it, and another thread taking from it.
Java 5 comes with blocking queue implementations in the java.util.concurrent package. You can read about that class in my java.util.concurrent.BlockingQueue tutorial. Even if Java 5 comes with a blocking queue implementation, it can be useful to know the theory behind their implementation.
阻塞队列实现是在java.util.concurrent.BlockingQueue ,这是接口

Blocking Queue Implementation

The implementation of a blocking queue looks similar to a Bounded Semaphore. Here is a simple implementation of a blocking queue:
blocking queue的实现类似于Bounded Semaphore

public class BlockingQueue {

  private List queue = new LinkedList();
  private int  limit = 10;

  public BlockingQueue(int limit){
    this.limit = limit;
  }

//入队
  public synchronized void enqueue(Object item)
  throws InterruptedException  {
    while(this.queue.size() == this.limit) {
      wait(); //等待有元素出队
    }
    //此时queue.size()<limit 也就是有空位,从而不用等待,直接入队
    this.queue.add(item);
    if(this.queue.size() == 1) {
    //说明之前的队是空的,现在有元素了,从而让之前因没元素无法出队的线程执行
      notifyAll();
    }
  }


  public synchronized Object dequeue()
  throws InterruptedException{
    while(this.queue.size() == 0){
      wait(); //等待有元素入队
    }
    if(this.queue.size() == this.limit){
     //因为此时堆满,若出队,则queue.size()<limit,从而可以让其他线程入队notifyAll()
      notifyAll(); 
    }
    //若0<queue.size()<limit,则说明队伍有元素,可以直接出队。
    return this.queue.remove(0);
  }

}

在这里插入图片描述
Notice how notifyAll() is only called from enqueue() and dequeue() if the queue size is equal to the size bounds (0 or limit). If the queue size is not equal to either bound when enqueue() or dequeue() is called, there can be no threads waiting to either enqueue or dequeue items.
请注意,如果队列大小等于大小界限(0或限制),则仅从enqueue()和dequeue()调用notifyAll()的方式。 如果在调用enqueue()或dequeue()时队列大小不等于绑定的大小,则没有线程等待入队或出队。

Java BlockingQueue Example

以下是基于典型的生产者-使用者场景的一个用例。注意,BlockingQueue 可以安全地与多个生产者和多个使用者一起使用。

class Producer implements Runnable {
   private final BlockingQueue queue;
   Producer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
 /*
 produce()方法是线程私有,所以它与线程是一一对应的
 quequ.put()是线程安全的,其放入队列的对象是唯一的。
 */
       while(true) { queue.put(produce()); } 
     } catch (InterruptedException ex) { ... handle ...}
   }

   Object produce() { ... }
 }

 class Consumer implements Runnable {
   private final BlockingQueue queue;
   Consumer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
     /*
     queue.take()是线程安全的 也就是某个线程取出一个元素时,其他线程不会对这个元素进行取出更
    改等操作 Consumer是线程私有的,所以consume()并不用加synchronized
    */
       while(true) { consume(queue.take()); } 
     } catch (InterruptedException ex) { ... handle ...}
   }
   void consume(Object x) { ... }
 }

 class Setup {
   void main() {
     BlockingQueue q = new SomeQueueImplementation();
     Producer p = new Producer(q);
     Consumer c1 = new Consumer(q);
     Consumer c2 = new Consumer(q);
     new Thread(p).start();
     new Thread(c1).start();
     new Thread(c2).start();
   }
 }
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值