集合框架 Queue---SynchronousQueue

来源:互联网 发布:unity3d怎样设置透明 编辑:程序博客网 时间:2024/05/02 02:19
public class SynchronousQueue<E>
extends AbstractQueue<E>
implements BlockingQueue<E>, Serializable

一种阻塞队列,其中每个插入操作必须等待另一个线程的对应移除操作 ,反之亦然。同步队列没有任何内部容量,甚至连一个队列的容量都没有。不能在同步队列上进行peek,因为仅在试图要移除元素时,该元素才存在;除非另一个线程试图移除某个元素,否则也不能(使用任何方法)插入元素;也不能迭代队列,因为其中没有元素可用于迭代。队列的 是尝试添加到队列中的首个已排队插入线程的元素;如果没有这样的已排队线程,则没有可用于移除的元素并且poll() 将会返回 null。对于其他 Collection 方法(例如 contains),SynchronousQueue 作为一个空 collection。此队列不允许null 元素。

同步队列类似于 CSP 和 Ada 中使用的 rendezvous 信道。它非常适合于传递性设计,在这种设计中,在一个线程中运行的对象要将某些信息、事件或任务传递给在另一个线程中运行的对象,它就必须与该对象同步。

对于正在等待的生产者和使用者线程而言,此类支持可选的公平排序策略。默认情况下不保证这种排序。但是,使用公平设置为 true 所构造的队列可保证线程以 FIFO 的顺序进行访问。

此类及其迭代器实现 CollectionIterator 接口的所有可选 方法。

此类是 Java Collections Framework 的成员。

从以下版本开始:
1.5
另请参见:
序列化表格

构造方法摘要SynchronousQueue()
          创建一个具有非公平访问策略的 SynchronousQueueSynchronousQueue(boolean fair)
          创建一个具有指定公平策略的 SynchronousQueue

注意1:它一种阻塞队列,其中每个 put 必须等待一个 take,反之亦然。
   同步队列没有任何内部容量,甚至连一个队列的容量都没有。
 注意2:它是线程安全的,是阻塞的。
 注意3:不允许使用 null 元素。
 注意4:公平排序策略是指调用put的线程之间,或take的线程之间。
 公平排序策略可以查考ArrayBlockingQueue中的公平策略。
 注意5:SynchronousQueue的以下方法很有趣:
    * iterator() 永远返回空,因为里面没东西。
    * peek() 永远返回null。
    * put() 往queue放进去一个element以后就一直wait直到有其他thread进来把这个element取走。
    * offer() 往queue里放一个element后立即返回,如果碰巧这个element被另一个thread取走了,offer方法返回true,认为offer成功;否则返回false。
    * offer(2000, TimeUnit.SECONDS) 往queue里放一个element但是等待指定的时间后才返回,返回的逻辑和offer()方法一样。
    * take() 取出并且remove掉queue里的element(认为是在queue里的。。。),取不到东西他会一直等。
    * poll() 取出并且remove掉queue里的element(认为是在queue里的。。。),只有到碰巧另外一个线程正在往queue里offer数据或者put数据的时候,该方法才会取到东西。否则立即返回null。
    * poll(2000, TimeUnit.SECONDS) 等待指定的时间然后取出并且remove掉queue里的element,其实就是再等其他的thread来往里塞。
    * isEmpty()永远是true。
    * remainingCapacity() 永远是0。
    * remove()和removeAll() 永远是false。


它模拟的功能类似于生活中一手交钱一手交货这种情形,像那种货到付款或者先付款后发货模型不适合使用SynchronousQueue。
首先要知道SynchronousQueue没有容纳元素的能力,即它的isEmpty()方法总是返回true,但是给人的感觉却像是只能容纳一个元素。


面使用SynchronousQueue模拟只能生产一个产品的生产者-消费者模型

[java] view plaincopy
  1. import java.util.concurrent.SynchronousQueue;  
  2.   
  3. class Producer extends Thread {  
  4.     private SynchronousQueue<Integer> queue;  
  5.     private int count;  
  6.   
  7.     public Producer(SynchronousQueue queue) {  
  8.         this.queue = queue;  
  9.         count = 0;  
  10.     }  
  11.   
  12.     @Override  
  13.     public void run() {  
  14.   
  15.         while (true) {  
  16.             try {  
  17.                 sleep(3000);  
  18.             } catch (InterruptedException e) {  
  19.                 e.printStackTrace();  
  20.             }  
  21.             if (queue.offer(count)) {  
  22.                 System.out.println("Producer插入: " + count++);  
  23.             }  
  24.         }  
  25.     }  
  26. }  
  27.   
  28. class Consumer extends Thread {  
  29.     private SynchronousQueue<Integer> queue;  
  30.   
  31.     public Consumer(SynchronousQueue queue) {  
  32.         this.queue = queue;  
  33.     }  
  34.   
  35.     @Override  
  36.     public void run() {  
  37.   
  38.         while (true) {  
  39.             try {  
  40.                 System.out.println("Consumer取出: " + queue.take());  
  41.                 sleep(3000);  
  42.             } catch (InterruptedException e) {  
  43.                 e.printStackTrace();  
  44.             }  
  45.         }  
  46.     }  
  47. }  
  48.   
  49. public class SynchronousQueueDemo {  
  50.     public static void main(String[] args) {  
  51.         // 使用true参数,使queue遵守FIFO  
  52.         SynchronousQueue queue = new SynchronousQueue<Integer>(true);  
  53.           
  54.         Producer p = new Producer(queue);  
  55.         Consumer c = new Consumer(queue);  
  56.           
  57.         p.start();  // queue遵守FIFO,所以先输出 "Producer插入: 0"  
  58.         c.start();  
  59.           
  60.           
  61.     }  
  62. }