我們知道,線程池中的所有線程都是由統一的線程工廠來創建的,當我們指定線程工廠時,線程池中的所有線程會使用我們指定的線程工廠來創建線程;但如果沒有指定線程工廠,則會使用默認的線程工廠 DefaultThreadFactory 來創建線程,核心源碼如下:
DefaultThreadFactory() { @SuppressWarnings("removal") SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-";}
那么問題來了,面試官問的是“如何實現優先級線程池?”,為什么我們一上來先講了線程工廠呢?
這是因為,當我們講到線程池優先級的時候,我們首先會想到線程的優先級,所以按照慣性思考,當面試官問到如何使用實現優先級線程池時,我們首先會考慮是不是在創建線程池的時候,可以通過某種方法來創建不同的線程優先級,從而實現優先級線程池?這就是開頭我們一上來就講線程工廠的原因。
那在線程工廠中如何設置線程的優先級呢?
它的設置也比較簡單,如下代碼所示:
import java.util.concurrent.ThreadFactory;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class CustomThreadPoolExecutorDemo { public static void main(String[] args) { // 自定義線程工廠 ThreadFactory threadFactory = new CustomThreadFactory(); // 創建線程池 ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), threadFactory); // 提交任務 executor.execute(() -> System.out.println("Task 1")); executor.execute(() -> System.out.println("Task 2")); // 關閉線程池 executor.shutdown(); } static class CustomThreadFactory implements ThreadFactory { @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r); // 設置線程優先級為最低優先級 thread.setPriority(Thread.MIN_PRIORITY); return thread; } }}
但是這種方式也有問題,那就是線程工廠是統一的,所以即使能在線程工廠中設置線程的優先級,那么也是將整個線程池中的所有線程都設置成統一的優先級了,而不能解決咱們本文提出的問題的,那如何才能實現優先級線程池呢?
轉念一想,既然不能在線程優先級上下功夫,但我們是否可以在線程池的任務隊列上動點心思呢?
此時我們想到,可以使用 PriorityBlockingQueue 優先級隊列來對任務進行排序啊(PriorityBlockingQueue 天生支持按照優先級自動排序任務的),這樣不就能保證優先級高的任務會被線程池優先獲取并執行了嘛!
所以,有時候一條路走不通的時候,我們可以嘗試換一個思路再試試。
我們先來測試一下 PriorityBlockingQueue 的使用,以嘗試其可行性,示例代碼如下:
import java.util.concurrent.PriorityBlockingQueue;public class PriorityBlockingQueueExample { public static void main(String[] args) { PriorityBlockingQueue<Task> priorityQueue = new PriorityBlockingQueue<>(); // 添加任務到優先級隊列 priorityQueue.add(new Task("Task 1", 1)); priorityQueue.add(new Task("Task 4", 4)); priorityQueue.add(new Task("Task 3", 3)); priorityQueue.add(new Task("Task 2", 2)); // 從優先級隊列中取出任務并執行 while (!priorityQueue.isEmpty()) { Task task = priorityQueue.poll(); if (task != null) { task.execute(); } } } static class Task implements Comparable<Task> { private String name; private int priority; public Task(String name, int priority) { this.name = name; this.priority = priority; } public void execute() { System.out.println("Executing task: " + name); } @Override public int compareTo(Task o) { return Integer.compare(this.priority, o.priority); } }}
以上程序的執行結果如下:
從上述結果和代碼可以看出,我們添加任務的順序是:1、4、3、2,但最終會按照優先級排隊執行的順序是:1、2、3、4,執行結果符合我們的預期,優先級高的任務先被執行了(數字越小,優先級越高)。
因此,我們實現的優先級線程池的最終代碼如下:
import java.util.concurrent.BlockingQueue;import java.util.concurrent.PriorityBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class PriorityThreadPool { public static void main(String[] args) { BlockingQueue<Runnable> queue = new PriorityBlockingQueue<>(1000); ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, queue ); for (int i = 0; i < 100; i++) { int finalI = i; executor.execute(new PriorityTask(i, () -> { try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("優先級:" + finalI); })); } } static class PriorityTask implements Runnable, Comparable<PriorityTask> { private final int priority; private final Runnable task; public PriorityTask(int priority, Runnable task) { this.priority = priority; this.task = task; } @Override public void run() { task.run(); } @Override public int compareTo(PriorityTask other) { // 優先級高的任務應該排在前面(數字越小優先級越大) return Integer.compare(this.priority, other.priority); } }}
以上程序執行結果如下:
從上述結果可以看出,線程池是完全按照優先級從高到低的順序執行的(數字越小優先級越高),如果將 compareTo 中的排序方法倒置之后,那么線程池的執行順序就完全相反了,可見使用 PriorityBlockingQueue 實現優先級線程池的效果非常顯著。
本文鏈接:http://www.tebozhan.com/showinfo-26-89400-0.html小米面試:如何實現優先級線程池?
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com