「原創宣告:保留所有權利,禁止轉載」
在之前的 Java 執行緒池實踐當中,我遇到了任務優先順序的問題。最終採取的方案是新增一個執行緒池作為執行高優任務,然後將普通執行緒池的在執行任務執行,先去判斷高優執行緒池是否有等待任務,如果有就先執行高優執行緒池等待佇列中的任務。
雖然後期給普通非同步執行緒池增加了雙向連結串列,直接採取插隊模式執行,但是也讓非同步任務更加複雜了。所以經過一些 java.util.concurrent
包的重新學習,得到了最優的答案,就是 java.util.concurrent.PriorityBlockingQueue
。
PriorityBlockingQueue 簡介
java.util.concurrent.PriorityBlockingQueue
是 Java 併發包中的一個執行緒安全的優先順序阻塞佇列。它是基於優先順序的元素順序,具有以下特點:
-
執行緒安全:
PriorityBlockingQueue
是執行緒安全的,可以在多執行緒環境下安全地進行操作,而不需要額外的同步手段。
-
無界佇列:
PriorityBlockingQueue
是一個無界佇列,可以無限制地新增元素,因此不會因為佇列滿而阻塞生產者執行緒。 -
基於優先順序的元素順序:
PriorityBlockingQueue
中的元素按照優先順序順序進行排序,具有較高優先順序的元素會被優先出隊。預設情況下,元素需要實現Comparable
介面來定義它們的優先順序,也可以在建構函式中提供一個Comparator
來自定義優先順序順序。 -
阻塞操作: 當佇列為空時,從
PriorityBlockingQueue
中獲取元素的操作會阻塞執行緒,直到佇列中有元素可用;當佇列滿時,向PriorityBlockingQueue
中新增元素的操作也會阻塞執行緒,直到佇列有足夠的空間。 -
不支援空元素:
PriorityBlockingQueue
不支援新增空元素,即元素不能為 null。
PriorityBlockingQueue
可以用於實現基於優先順序的任務排程、事件處理等場景,其中優先順序高的任務或事件會優先被處理。它提供了一種高效的方式來管理和處理具有不同優先順序的元素。
多優先順序執行緒池
下面是我自己的實現邏輯:
- 首先建立一個功能類,實現
java.lang.Comparable
和java.lang.Runnable
。 - 制定優先順序規則,通常定義一個屬性
int
型別,代表優點等級。 - 封裝 execute() 方法,用來向執行緒池提交任務。
具體程式碼如下:
/**
* 多優先順序執行緒池
*/
static ThreadPoolExecutor levelPool = createPool(POOL_SIZE, POOL_SIZE, ALIVE_TIME, new PriorityBlockingQueue<PriorityTask>(), getFactory("L"), new ThreadPoolExecutor.DiscardPolicy())
/**
* 執行優先順序任務
* @param task
* @return
*/
static def executeLevel(PriorityTask task) {
levelPool.execute(task)
}
/**
* 執行優先順序任務,設定優先順序
* @param priority
* @param closure
* @return
*/
static def executeLevel(int priority, Closure closure) {
levelPool.execute(new PriorityTask(priority) {
@Override
void run() {
closure()
}
})
}
/**
* 執行優先順序任務,使用預設優先順序
* @param closure
* @return
*/
static def executeLevel(Closure closure) {
levelPool.execute(new PriorityTask(PRIORITY_LEVEL_DEFAULT) {
@Override
void run() {
closure()
}
})
}
/**
* 優先順序任務,用於優先順序執行緒池
*/
static abstract class PriorityTask implements Runnable, Comparable<PriorityTask> {
int priority
PriorityTask(int priority) {
this.priority = priority
}
/**
* 比較方法,用於優先順序佇列,優先順序越高,越先執行
* @param o
* @return
*/
@Override
int compareTo(PriorityTask o) {
return this.priority - o.priority
}
}
測試
我們來寫一個測試用例,往執行緒池提交優先順序不斷提升的任務,列印任務執行時間。
ThreadPoolUtil.getLevelPool().setCorePoolSize(1);
ThreadPoolUtil.getLevelPool().setMaximumPoolSize(1);
for (int i = 0; i < 10; i++) {
ThreadPoolUtil.executeLevel(new ThreadPoolUtil.PriorityTask(10 - i) {
@Override
public void run() {
SourceCode.sleep(0.01);
System.out.println(this.getPriority());
}
});
}
控制檯列印:
10
1
2
3
4
5
6
7
8
9
看起來是比較符合預期的。
- 2021 年原創合集
- 2022 年原創合集
- 2023 年原創合集
- 服務端功能測試
- 效能測試專題
- Java、Groovy、Go、Python
- 單元&白盒&工具合集
- 測試方案&BUG&爬蟲&UI 自動化
- 測試理論雞湯
- 社群風采&影片合集
如果覺得我的文章對您有用,請隨意打賞。您的支援將鼓勵我繼續創作!
打賞支援
暫無回覆。