介绍:

基于优先级堆的无界优先级队列。优先级队列的元素按照其自然顺序进行排序,或者根据构造队列时提供的 Comparator 进行排序,具体取决于所使用的构造方法。

优先级队列不允许使用 null 元素。

依靠自然顺序的优先级队列还不允许插入不可比较的对象。

此队列的 是按指定排序方式确定的最小 元素。如果多个元素都是最小值,则头是其中一个元素——选择方法是任意的。

优先级队列是无界的,但是有一个内部容量控制着用于存储队列元素的数组大小,它通常至少等于队列的大小。

随着不断向优先级队列添加元素,其容量会自动增加。无需指定容量增加策略的细节。

虽然此队列逻辑上是无界的,但是资源被耗尽时试图执行 add 操作也将失败。

1、PriorityQueue

非同步队列。

在多线程同时读写时会出现异常。

2、PriorityBlockingQueue

  同步队列。

  适用于多线程环境中。

3、实现方式:

PriorityQueue部分是测试PriorityQueue用,因为在多线程时有同步问题,可能在开发中不适用。

     ①队列中元素用 Comparator 进行排序

     要自己实现Comparator 接口类。添加进优先队列中的数据,Queue会调用Comparator进行比较,小的数据会放在Queue的前部,反之,放在后部。最小的数据会放在Queue的头部。(具体实现?)

     放在Queue中的数据只有添加时才进行比较,加入后的位置是不会改变的——所以元素比较用的值最好是固定的,否则取出的数据有可能不是最优先的。

     Comparators实现代码:

Comparator实现类

import java.util.Comparator;
public class Comparators implements Comparator<Executor> {
    @Override
    public int compare(Executor paramT1, Executor paramT2) {
        return (int)(paramT1.getDeadline() - paramT2.getDeadline());
    }
}

Executor实现代码:

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Date;
public class Executor implements Runnable{
     
    private long createTime;
    private long timeout;
     
    private OutputStreamWriter writer;
     
    public Executor(long timeout, OutputStreamWriter writer){
        this.timeout = timeout;
        createTime = new Date().getTime();
        this.writer = writer;
    }
     
    @Override
    public void run() {
        try {
            writer.write("createTime>>[" + createTime + "]  timeout>>[" + timeout + "] hashcode>>[" + (createTime + timeout) + "]\r\n");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
     
    public long getDeadline(){
        return this.createTime + this.timeout;
    }
}

写入文件的原因是多线程写入会保证写入的顺序,基本可以保证取得的数据的顺序是Queue中的顺序。

测试代码

class Consumer implements Runnable {
    private AtomicInteger counter;
    private PriorityBlockingQueue<Executor> runQueue; 
    public Consumer(PriorityBlockingQueue<Executor> runQueue, AtomicInteger counter){
//  private PriorityQueue<Executor> runQueue;
//  public Consumer(PriorityQueue<Executor> runQueue, AtomicInteger counter){
        this.runQueue = runQueue;
        this.counter = counter;
    }
    @Override
    public void run() {
        Executor exe = null;
        while((exe = runQueue.poll()) != null){
            exe.run();
            counter.decrementAndGet();
        }
    }
}
class Producer implements Runnable {
    private AtomicInteger counter;
    private OutputStreamWriter writer;
     
    private PriorityBlockingQueue<Executor> runQueue;
    public Producer(PriorityBlockingQueue<Executor> runQueue, AtomicInteger counter,
            OutputStreamWriter writer){
//  private PriorityQueue<Executor> runQueue;
//  public Producer(PriorityQueue<Executor> runQueue, AtomicInteger counter, 
//      OutputStreamWriter writer){
        this.runQueue = runQueue;
        this.counter = counter;
        this.writer = writer;
    }
     
    @Override
    public void run() {
        Random rand = new Random();
        for(int i=0; i < 1000; i++){
            long timeout = rand.nextInt(10000000);
            Executor exe = new Executor(timeout, writer);
            runQueue.offer(exe);
            counter.incrementAndGet();
        }
    }
}
 
    //测试函数代码
    public static void TestWithComparator() throws InterruptedException, IOException{
        AtomicInteger counter = new AtomicInteger();
//      PriorityQueue<Executor> runQueue = new PriorityQueue<Executor>(1000);
        PriorityBlockingQueue<Executor> runQueue = new PriorityBlockingQueue<Executor>(1000, new Comparators());
        OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("e:\\priorityQueue.txt"));
        ExecutorService producerPool = Executors.newFixedThreadPool(16);
        long start = System.nanoTime();
        for(int i=0; i < 1000; i++){
            producerPool.execute(new Producer(runQueue, counter, writer));
        }
        producerPool.shutdown();
        while(!producerPool.isTerminated()){
             
        }
        long end = System.nanoTime();
        System.out.println("comparator add time is " + (end - start));
        ExecutorService consumerPool = Executors.newFixedThreadPool(16);
        start = System.nanoTime();
        for(int i=0; i < 16; i++){
            consumerPool.execute(new Consumer(runQueue, counter));
        }
        consumerPool.shutdown();
        while(!consumerPool.isTerminated()){
            ;
        }
        end = System.nanoTime();
        System.out.println("comparator exe time is " + (end - start));
        System.out.println(counter.get());
        writer.close();
    }

②队列中元素实现Comparable接口进行排序

添加入队列中的元素要实现Comparable接口,排序时调用实现Comparable接口的compareTo方法进行比较,排序的结果同①。

 

ExecutorCmp

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Date;
public class ExecutorCmp implements Runnable, Comparable<ExecutorCmp>{
     
    private long createTime;
     
    private long timeout;
     
    private OutputStreamWriter writer;
     
    public ExecutorCmp(long timeout, OutputStreamWriter writer){
        this.timeout = timeout;
        createTime = new Date().getTime();
        this.writer = writer;
    }
     
    @Override
    public void run() {
        try {
            writer.write("createTime>>[" + createTime + "]  timeout>>[" + timeout + "] hashcode>>[" + (createTime + timeout) + "]\r\n");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
     
    @Override
    public int compareTo(ExecutorCmp arg0) {
        return (int)((this.createTime + this.timeout) - (arg0.createTime + arg0.timeout));
    }
}

Comparable测试代码

class CmpConsumer implements Runnable {
    private AtomicInteger counter;
    private PriorityBlockingQueue<ExecutorCmp> runQueue;  
    public CmpConsumer(PriorityBlockingQueue<ExecutorCmp> runQueue, AtomicInteger counter){
//  private PriorityQueue<Executor> runQueue;
//  public Consumer(PriorityQueue<Executor> runQueue, AtomicInteger counter){
        this.runQueue = runQueue;
        this.counter = counter;
    }
    @Override
    public void run() {
        ExecutorCmp exe = null;
        while((exe = runQueue.poll()) != null){
            exe.run();
            counter.decrementAndGet();
        }
    }
}
class CmpProducer implements Runnable {
    private AtomicInteger counter;
    private OutputStreamWriter writer;
     
    private PriorityBlockingQueue<ExecutorCmp> runQueue;
    public CmpProducer(PriorityBlockingQueue<ExecutorCmp> runQueue, AtomicInteger counter,
            OutputStreamWriter writer){
//  private PriorityQueue<Executor> runQueue;
//  public Producer(PriorityQueue<Executor> runQueue, AtomicInteger counter, 
//      OutputStreamWriter writer){
        this.runQueue = runQueue;
        this.counter = counter;
        this.writer = writer;
    }
     
    @Override
    public void run() {
        Random rand = new Random();
        for(int i=0; i < 1000; i++){
            long timeout = rand.nextInt(10000000);
            ExecutorCmp exe = new ExecutorCmp(timeout, writer);
            runQueue.offer(exe);
            counter.incrementAndGet();
        }
    }
}
 
   //测试函数代码:
    public static void testWithComparable() throws InterruptedException, IOException{
        AtomicInteger counter = new AtomicInteger();
        PriorityBlockingQueue<ExecutorCmp> runQueue = new PriorityBlockingQueue<ExecutorCmp>(1000);
        OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("e:\\priorityQueue1.txt"));
        ExecutorService producerPool = Executors.newFixedThreadPool(16);
        long start = System.nanoTime();
        for(int i=0; i < 1000; i++){
            producerPool.execute(new CmpProducer(runQueue, counter, writer));
        }
        producerPool.shutdown();
        while(!producerPool.isTerminated()){
             
        }
        long end = System.nanoTime();
        System.out.println("comparatable add time is " + (end - start));
         
        ExecutorService consumerPool = Executors.newFixedThreadPool(16);
        start = System.nanoTime();
        for(int i=0; i < 16; i++){
            consumerPool.execute(new CmpConsumer(runQueue, counter));
        }
        consumerPool.shutdown();
        while(!consumerPool.isTerminated()){
            ;
        }
        end = System.nanoTime();
        System.out.println("comparatable exe time is " + (end - start));
        System.out.println(counter.get());
        writer.close();
    }

4、在ThreadPoolExecutor中的应用方式

PriorityBlockingQueue保存这些Runnable,必须对Runnable进行封装,并实现Comparable接口。

      代码如下:

class SafTask implements Runnable, Comparable<SafTask> {
     
    private int order;
     
    public SafTask(int order){
        this.order = order;
    }
     
    public void run() {
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(order);
    }
    @Override
    public int compareTo(SafTask other) {
         
        return this.order - other.order;
    }
}
 
//测试代码
        BlockingQueue<Runnable> configQueue = new PriorityBlockingQueue<Runnable>();
        ThreadPoolExecutor stpe = new ThreadPoolExecutor(1, 10, 1000, TimeUnit.MILLISECONDS, configQueue);
         
        Random rand = new Random();
        for(int i = 0; i < 1000; i++){
            int order = rand.nextInt(1000);
            Thread.sleep(3);
            stpe.execute(new SafTask(order));
        }
        stpe.shutdown();

结论:

   1、使用PriorityBlockingQueue时元素实现Comparable接口进行排序性能上会高一些:

    comparator add time is 250168728

    comparator exe time is 2755292150

        *********************************************************************************

        comparatable add time is 218674112

        comparatable exe time is 2222345324

    2、在ThreadPoolExecutor中使用PriorityBlockingQueue时,要封装Runnable并实现Comparable接口