阻塞队列之PriorityBlockingQueue

PriorityBlockingQueue

特点:

1、可以指定内部元素的排序规则(即出队规则),即实现该接口的对象:java.util.Comparator

2、内部数据结构是对象数据组,Object[] queue;

3、默认长度:11,最大长度:Integer.MAX_VALUE - 8;

4、不支持放入空值,会抛异常:NullPointerException

5、放入元素有要求,二选一:

     A、元素对象不用实现:java.lang.Comparable,但是需要在构造参数中指定比较器:java.util.Comparator

     B、元素对象实现:java.lang.Comparable,构造无需指定比较器:java.util.Comparator

     必须二选一,否则会抛异常,如果两个条件都满足了,那么默认会优先按指定的比较器来比较排序;

构造:

    //1、无惨构造,使用默认长度11,不指定比较器,要求元素必须实现Comparable接口
    public PriorityBlockingQueue() {
        this(DEFAULT_INITIAL_CAPACITY, null);
    }

    //2、指定容量的构造,不指定比较器
    public PriorityBlockingQueue(int initialCapacity) {
        this(initialCapacity, null);
    } 

    //3、指定容量和比较器的构造,元素顺序按照比较器指定的比较规则来
    public PriorityBlockingQueue(int initialCapacity,
                                 Comparator comparator) {
        if (initialCapacity < 1)
            throw new IllegalArgumentException();
        this.lock = new ReentrantLock();
        this.notEmpty = lock.newCondition();
        this.comparator = comparator;
        this.queue = new Object[initialCapacity];
    }

    //4、通过指定集合构造队列
    public PriorityBlockingQueue(Collection c) {
        this.lock = new ReentrantLock();
        this.notEmpty = lock.newCondition();
        boolean heapify = true; // true if not known to be in heap order
        boolean screen = true;  // true if must screen for nulls
        if (c instanceof SortedSet) {
            SortedSet ss = (SortedSet) c;
            this.comparator = (Comparator) ss.comparator();
            heapify = false;
        }
        else if (c instanceof PriorityBlockingQueue) {
            PriorityBlockingQueue pq =
                (PriorityBlockingQueue) c;
            this.comparator = (Comparator) pq.comparator();
            screen = false;
            if (pq.getClass() == PriorityBlockingQueue.class) // exact match
                heapify = false;
        }
        Object[] a = c.toArray();
        int n = a.length;
        // If c.toArray incorrectly doesn't return Object[], copy it.
        if (a.getClass() != Object[].class)
            a = Arrays.copyOf(a, n, Object[].class);
        if (screen && (n == 1 || this.comparator != null)) {
            for (int i = 0; i < n; ++i)
                if (a[i] == null)
                    throw new NullPointerException();
        }
        this.queue = a;
        this.size = n;
        if (heapify)
            heapify();
    }

方法:

其方法和ArrayBlockingQueue和LinkedBlockingQueue类似,入队:add、offer、put;出队:remove、poll、take

其要注意的是:

1、入队时,元素会按照构造队列时指定的Comparator对象排序,或者,按照元素自身实现Comparable接口后的比较规则排序;

2、如果两种都满足,默认构造参数指定的Comparator有限;

应用场景:

1、放入队列的元素需要按照指定的规则排序出队,比如:带有不同优先级的任务,VIP客户的任务需要插队先处理;

使用示例:

import java.util.Comparator;
import java.util.concurrent.PriorityBlockingQueue;

/**
 * PriorityQueue 
* 特点:
* 可以定义排序规则(即出队规则)的阻塞队列(针对已经在队列内的元素)
* 数据结构:对象数组
* 默认长度11
* 不能放入空值
* 放入元素有要求,二选一: * 1、元素对象不用实现:java.lang.Comparable,但是需要在构造参数中指定比较器:java.util.Comparator * 2、元素对象实现:java.lang.Comparable,构造无需指定比较器:java.util.Comparator * 必须二选一,否则会抛异常,如果两个条件都满足了,那么默认会优先按指定的比较器来比较排序; * */ public class PriorityBlockingQueueTest { private PriorityBlockingQueue priorityBlockingQueue = new PriorityBlockingQueue(10, new Comparator() { public int compare(CustTask o1, CustTask o2) { return o1.getPriority() - o2.getPriority();// 优先级小的靠前排 } }); //注意:采用这种不指定比较器的构造,要求放入的元素必须实现Comparable接口,否则会抛异常; private PriorityBlockingQueue priorityBlockingQueue2 = new PriorityBlockingQueue(); public PriorityBlockingQueueTest() { } class CustTask { private String name; private int priority; public CustTask(String name, int priority) { this.name = name; this.priority = priority; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPriority() { return priority; } public void setPriority(int priority) { this.priority = priority; } @Override public String toString() { return "name:" + this.getName() + " , priority:" + this.getPriority(); } } private void test() { for (int i = 0; i < 10; i++) { priorityBlockingQueue.offer(new CustTask("name" + i, 20 - i)); } CustTask custTask = null; while (true) { custTask = priorityBlockingQueue.poll();// 为null表示没有元素了,不阻塞 if (null != custTask) { System.out.println(custTask.toString()); } else { break; } } System.out.println("over"); } public static void main(String[] args) { new PriorityBlockingQueueTest().test(); } }

 

你可能感兴趣的:(多线程)