阻塞队列之PriorityBlockingQueue

PriorityBlockingQueue

特点:

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

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

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

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

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

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

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

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

构造:

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

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

    //3、指定容量和比较器的构造,元素顺序按照比较器指定的比较规则来
    public PriorityBlockingQueue(int initialCapacity,
                                 Comparator<? super E> 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<? extends E> 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<? extends E> ss = (SortedSet<? extends E>) c;
            this.comparator = (Comparator<? super E>) ss.comparator();
            heapify = false;
        }
        else if (c instanceof PriorityBlockingQueue<?>) {
            PriorityBlockingQueue<? extends E> pq =
                (PriorityBlockingQueue<? extends E>) c;
            this.comparator = (Comparator<? super E>) 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 <br>
 * 特点:<br>
 * 可以定义排序规则(即出队规则)的阻塞队列(针对已经在队列内的元素)<br>
 * 数据结构:对象数组 <br>
 * 默认长度11 <br>
 * 不能放入空值 <br>
 * 放入元素有要求,二选一:
 * 1、元素对象不用实现:java.lang.Comparable<T>,但是需要在构造参数中指定比较器:java.util.Comparator<T>
 * 2、元素对象实现:java.lang.Comparable<T>,构造无需指定比较器:java.util.Comparator<T>
 * 必须二选一,否则会抛异常,如果两个条件都满足了,那么默认会优先按指定的比较器来比较排序;
 * 
 */
public class PriorityBlockingQueueTest {

	private PriorityBlockingQueue<CustTask> priorityBlockingQueue = new PriorityBlockingQueue<CustTask>(10,
			new Comparator<CustTask>() {
				public int compare(CustTask o1, CustTask o2) {
					return o1.getPriority() - o2.getPriority();// 优先级小的靠前排
				}
			});

	//注意:采用这种不指定比较器的构造,要求放入的元素必须实现Comparable接口,否则会抛异常;
	private PriorityBlockingQueue<CustTask> priorityBlockingQueue2 = new PriorityBlockingQueue<CustTask>();

	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();
	}
}

猜你喜欢

转载自blog.csdn.net/tobearc/article/details/87954602
今日推荐