多優先級線程池實踐

在之前的Java線程池實踐當中,我遇到了任務優先級的問題。最終採取的方案是新增一個線程池作爲執行高優任務,然後將普通線程池的在執行任務執行,先去判斷高優線程池是否有等待任務,如果有就先執行高優線程池等待隊列中的任務。

雖然後期給普通異步線程池增加了雙向鏈表,直接採取插隊模式執行,但是也讓異步任務更加複雜了。所以經過一些 java.util.concurrent 包的重新學習,得到了最優的答案,就是 java.util.concurrent.PriorityBlockingQueue

PriorityBlockingQueue簡介

java.util.concurrent.PriorityBlockingQueue 是 Java 併發包中的一個線程安全的優先級阻塞隊列。它是基於優先級的元素順序,具有以下特點:

  1. 線程安全: PriorityBlockingQueue 是線程安全的,可以在多線程環境下安全地進行操作,而不需要額外的同步手段。
  2. 無界隊列: PriorityBlockingQueue 是一個無界隊列,可以無限制地添加元素,因此不會因爲隊列滿而阻塞生產者線程。
  3. 基於優先級的元素順序: PriorityBlockingQueue 中的元素按照優先級順序進行排序,具有較高優先級的元素會被優先出隊。默認情況下,元素需要實現 Comparable 接口來定義它們的優先級,也可以在構造函數中提供一個 Comparator 來自定義優先級順序。
  4. 阻塞操作: 當隊列爲空時,從 PriorityBlockingQueue 中獲取元素的操作會阻塞線程,直到隊列中有元素可用;當隊列滿時,向 PriorityBlockingQueue 中添加元素的操作也會阻塞線程,直到隊列有足夠的空間。
  5. 不支持空元素: PriorityBlockingQueue 不支持添加空元素,即元素不能爲 null。

PriorityBlockingQueue 可以用於實現基於優先級的任務調度、事件處理等場景,其中優先級高的任務或事件會優先被處理。它提供了一種高效的方式來管理和處理具有不同優先級的元素。

多優先級線程池

下面是我自己的實現邏輯:

  1. 首先創建一個功能類,實現 java.lang.Comparablejava.lang.Runnable
  2. 制定優先級規則,通常定義一個屬性 int 類型,代表優點等級。
  3. 封裝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

看起來是比較符合預期的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章