java中的阻塞队列和性能对比

java.util.PriorityQueue
 

E 集合中所保存元素的类型。

public class PriorityQueue extends AbstractQueue implements Serializable
 

一个基于优先级堆的极大优先级队列。此队列按照在构造时所指定的顺序对元素排序,既可以 根据元素的自然顺序(Comparable)来指定排序,也可以根据Comparator来指定,这取决于使用那种构造方法。优先级队列不允许null元 素。依靠自然排序的优先级队列还不允许插入不可比较的对象,这样做可能导致ClassCastException。

此队列的头是按指定排序的最小元素。如果有多个元素都是最小值,则头是其中一个元素——选择方法是任意的。队列检索操作poll , remove , peek 和 element访问处于队列头的元素。

优先级队列是无界的,但是有一个内部容量,控制着用于存储队列元素的数组的大小。它总是至少与队列的大小相同。随着不断向优先级队列中添加元素,其容量会自动增加。无需指定容量增加策略的细节。

注意,此实现不是同步的。如果多个线程中的任意线程从结构上修改了列表,则这些线程不应同时访问PriorityQueue实例。相反,请使用线程安全的PriorityBlockingQueue类。

接口BlockingQueue

public interface BlockingQueue extends Queue
 

支持两个附加操作的Queue,这两个操作是:检索元素时等待队列变为非空,以及存储元素时等待空间变得可用。

BlockingQueue不接受null元素。

BlockingQueue可以是限定容量的。

BlockingQueue实现主要用于生产者-使用者队列,但它另外还支持Collection接口。因此,举例来说,使用remove(x)从队列中移除任意一个元素是有可能的。然而,这种操作通常不会有效执行,只能有计划地偶尔使用,比如在取消排队信息时。

BlockingQueue实现是线程安全的。注意,BlockingQueue可以安全地与多个生产者和多个使用者一起使用。


class Producer implements Runnable {
   private final BlockingQueue queue;
   Producer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       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 {
       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();
   }
}
 

此接口是Java Collecitons Framework的成员。


类PriorityBlockingQueue


public class PriorityBlockingQueue

extends AbstractQueue implments BlockingQueue ,Serializable
 

一个无界的阻塞队列,它使用与类PriorityQueue相同的顺序规则,并且提供了 阻塞检索的操作。虽然此队列逻辑上是无界的,但是由于资源被耗尽,所以试图执行添加操作可能会失败,导致OutOfMemoryError。此类不允许使 用null元素,依赖自然顺序的优先级队列也不允许插入不可比较的对象。

如果需要有序的遍历,则应考虑使用Arrays.sort(pq.toArray())


接口Compara

public interface Comparable
 

此接口强行对实现它的每个类的对象进行整体排序。次排序被称为该类的自然排序,类的 compareTo方法被称为它的自然比较方法。实现此接口的对象列表和数组可以通过Collections.sort(和Arrays.sort)进行 自动排序。实现此接口的对象可以用作有序映射表中的键或有序集合中的元素,无需指定比较器。


阻塞队列的性能对比

主要是比较offer跟poll两个方法的性能,开N个线程,每个线程往队列里写或者取500个整数。线程数 20 50 100 200 500 1000
LinkedBlockingQueue     15,0 31,15 32,16 63,32 203,47 563,110
ArrayBlockingQueue 15,0 16,15 31,15 47,16 125,47 364,68
PriorityBlockingQueue 78,78 172,188 360,422 813,969 3094,2641 6547,5453


逗号前的数字是offer测试花费的时间,逗号后的数字是poll测试花费的时间。
结论:
1、ArrayBlockingQueue性能优于LinkedBlockingQueue,但是LinkedBlockingQueue是无界的。
2、ArrayBlockingQueue和LinkedBlockingQueue的poll方法总是比offer方法快,并发越高,差距越大
3、ArrayBlockingQueue和LinkedBlockingQueue的性能远高于PriorityBlockingQueue,显然优先队列在比较优先级上的操作上耗费太多
4、PriorityBlockingQueue的offer方法与poll方法的性能差距很小,基本维持在近似1:1

你可能感兴趣的:(java)