使用数据结果的一个典型需求是排序列表。Java 为此提供了 PriorityBlockingQueue 。
您要加到 PriorityBlockingQueue 的所有元素必须实现 Comparable 接口。此接口有一个方法 compareTo() 。 此方法接受一个相同类型的对象作为参数。所以有2个对象进行比较,一个是执行此方法的对象(本地对象),一个是参数。 此方法的返回值:
当插入一个元素到 PriorityBlockingQueue 时,PriorityBlockingQueue 用 compareTo() 方法来决定插入元素的位置。 较大的元素将被放在队列的尾部。
PriorityBlockingQueue 的另一个重要特点是它是一个阻塞式数据结构。它有些方法在不能立即执行操作时,阻塞线程直到能执行时。
本节的示例代码在 com.elanzone.books.noteeg.chpt6.sect04 package中
数据类 : Event : 实现 Comparable<Event> 接口
private int thread; private int priority; public Event(int thread, int priority) { this.thread = thread; this.priority = priority; }
public int getThread() { return thread; } public int getPriority() { return priority; }
@Override public int compareTo(Event e) { if (this.priority > e.getPriority()) { return -1; } else if (this.priority < e.getPriority()) { return 1; } else { return 0; } }
Runnable 实现类: Task
private int id; private PriorityBlockingQueue<Event> queue; public Task(int id, PriorityBlockingQueue<Event> queue) { this.id = id; this.queue = queue; }
@Override public void run() { for (int i = 0; i < 1000; i++) { Event event = new Event(id, i); queue.add(event); } }
控制类 :Main
PriorityBlockingQueue<Event> queue = new PriorityBlockingQueue<>();
Thread taskThreads[] = new Thread[5]; for (int i = 0; i < taskThreads.length; i++) { Task task = new Task(i, queue); taskThreads[i] = new Thread(task); }
for (Thread taskThread : taskThreads) { taskThread.start(); } for (Thread taskThread : taskThreads) { try { taskThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } }
System.out.printf("Main: Queue Size: %d\n", queue.size()); for (int i = 0; i < taskThreads.length * 1000; i++) { Event event = queue.poll(); System.out.printf("Thread %s: Priority %d\n", event.getThread(), event.getPriority()); } System.out.printf("Main: Queue Size: %d\n", queue.size()); System.out.printf("Main: End of the program\n");
本例用 PriorityBlockingQueue 实现了一个事件对象的优先级队列。 如在介绍提到的,存储在 PriorityBlockingQueue 中的元素都必须实现 Comparable 接口。 所以您必须在 Event 类中实现 compareTo() 方法。
事件有优先级(priority)属性。priority 值大的将排在队列的前面。 实现 compareTo() 方法时,如果本地对象的优先级高过参数的优先级,则返回 -1;否则返回1;如果一样则返回0(此时 PriorityBlockingQueue 不保证元素的顺序)。
本例实现了 Task 类来添加 Event 对象到优先级队列。每个 task 对象用 add() 方法往队列添加 1000 个事件,优先级从 0 到 999。
Main 类的 main() 方法创建了5个 Task 对象并在对应的线程中执行。所有线程结束执行后,将所有元素输出到终端。 为了从队列获取元素,使用了 poll() 方法。此方法从队列返回并移除第一个元素。