
在之前的文章中已經為大家介紹了java并發編程的工具:BlockingQueue接口、ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue,本文為系列文章第五篇。
Java PriorityBlockingQueue隊列是BlockingQueue接口的實現類,它根據**priority**優先級確定隊列內元素對象的處理順序,也就是說在一個PriorityBlockingQueue隊列中,被添加到隊列中的元素,根據priority進行排序。PriorityBlockingQueue具有BlockingQueue阻塞隊列的一些特性,如果您不熟悉BlockingQueue可以參看我之前的文章。

## 1. PriorityBlockingQueue 特性
* PriorityBlockingQueue 是一個無界隊列(隊列內元素個數沒有上限),隊列容量可以自動增長。其初始化隊列容量為11,也可以通過構造函數參數initialCapacity指定其初始化容量。
* 不接受 NULL對象插入到PriorityBlockingQueue
* 添加到PriorityBlockingQueue隊列中的元素對應的Java類,通常需要實現Comparable接口或者是可以默認排序的對象(如數字、字符串),否則會拋出`ClassCastException`
* 可以使用java8 的Comparator提供自定義隊列內元素的排序規則,后文會舉例說明。
* 如果存在多個對象擁有相等的優先級,從隊列中poll獲取元素的時候可能獲取到其中任何一個元素。
* PriorityBlockingQueue 是線程安全的
## 2. PriorityBlockingQueue 應用實例
我們寫一個類`Employee`,該類實現了Comparable接口,所以其實例對象可以根據compareTo()函數定義的規則進行排序。
~~~
public class Employee implements Comparable<Employee> {
private Long id;
private String name;
private LocalDate dob;
//Getters and setters
public Employee(Long id, String name, LocalDate dob) {
super();
this.id = id;
this.name = name;
this.dob = dob;
}
@Override
public int compareTo(Employee emp) {
return this.getId().compareTo(emp.getId()); //根據id排序
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", dob=" + dob + "]";
}
}
~~~
構造一個PriorityBlockingQueue對象,并向其內部加入若干Employee對象,并使用poll方法從隊列內取出元素。
~~~
PriorityBlockingQueue<Employee> priorityBlockingQueue = new PriorityBlockingQueue<>();
priorityBlockingQueue.add(new Employee(1l, "AAA", LocalDate.now()));
priorityBlockingQueue.add(new Employee(4l, "CCC", LocalDate.now()));
priorityBlockingQueue.add(new Employee(5l, "BBB", LocalDate.now()));
priorityBlockingQueue.add(new Employee(2l, "FFF", LocalDate.now()));
priorityBlockingQueue.add(new Employee(3l, "DDD", LocalDate.now()));
priorityBlockingQueue.add(new Employee(6l, "EEE", LocalDate.now()));
while(true) {
Employee e = priorityBlockingQueue.poll();
System.out.println(e);
if(e == null) break;
}
~~~
根據上文中compareTo()方法定義的排序規則,按照id為優先級,所以從隊列中拿出對象并打印的順序如下:
~~~
Employee [id=1, name=AAA, dob=2021-03-25]
Employee [id=2, name=FFF, dob=2021-03-25]
Employee [id=3, name=DDD, dob=2021-03-25]
Employee [id=4, name=CCC, dob=2021-03-25]
Employee [id=5, name=BBB, dob=2021-03-25]
Employee [id=6, name=EEE, dob=2021-03-25]
~~~
## 3. 使用 Java8 Comparator 做優先級排序的實例
我們可以使用java 8 Comparator排序器,來定義優先級排序規則。使用構造方法**PriorityBlockingQueue(int initialCapacity, Comparator comparator)** 構造PriorityBlockingQueue隊列。
~~~
//以員工名稱的字符串自然正序進行排序
Comparator<Employee> nameSorter = Comparator.comparing(Employee::getName);
PriorityBlockingQueue<Employee> PriorityBlockingQueue = new PriorityBlockingQueue<>( 11, nameSorter );
//此處省略向隊列中添加對象,及循環取出對象打印的代碼,參考上文
~~~
按照員工姓名進行優先級排序,所以打印順序AAA、BBB、CCC、DDD、EEE、FFF
~~~
Employee [id=1, name=AAA, dob=2021-03-25]
Employee [id=5, name=BBB, dob=2021-03-25]
Employee [id=4, name=CCC, dob=2021-03-25]
Employee [id=3, name=DDD, dob=2021-03-25]
Employee [id=6, name=EEE, dob=2021-03-25]
Employee [id=2, name=FFF, dob=2021-03-25]
~~~
.
- 線程
- 1.進程和線程-鎖與信號量
- 2.Thread類線程狀態轉換
- 2.并發與并行-同步與異步
- 4.線程池
- 5.對象級別與類級別的同步鎖
- 6.創建線程的四種方式
- 7.臨界區-阻塞-活鎖-死鎖
- 2.JMM多線程模型
- JUC
- BlockingQueue
- ArrayBlockingQueue
- DelayQueue
- LinkedBlockingQueue
- PriorityBlockingQueue
- SynchronousQueue
- BlockingDeque
- ConcurrentHashMap
- CountDownLatch
- CyclicBarrier
- Exchanger
- AtomicInteger
- Lock
- Condition
- ReentrantLock讀寫鎖
- StampedLock
- Semaphore