package com.zang.concurrent.collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;
/**
*
* 線程池
*
* 要使用帶有ThreadFactory參數的ThreadPoolExecutor構造方法哦,這樣你就可以方便的設置線程名字啦。 less... (Ctrl+F1)
* Inspection info:
* 創建線程或線程池時請指定有意義的線程名稱,方便出錯時回溯。創建線程池的時候請使用帶ThreadFactory的構造函數,並且提供自定義ThreadFactory實現或者使用第三方實現。
*
* ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
* .setNameFormat("demo-pool-%d").build();
* ExecutorService singleThreadPool = new ThreadPoolExecutor(1, 1,
* 0L, TimeUnit.MILLISECONDS,
* new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
*
* singleThreadPool.execute(()-> System.out.println(Thread.currentThread().getName()));
* singleThreadPool.shutdown();
*
*
*
* public class TimerTaskThread extends Thread {
* public TimerTaskThread(){
* super.setName("TimerTaskThread"); …
* }
*
*
* @author Zhang Qiang
* @Date 2019/9/9 9:26
*/
public class ThreadPool {
/**
* 線程池
* newSingleThreadExecutor(),它的特點在於工作線程數目被限制為 1,操作一個無界的工作隊列,所以它保證了所有任務的都是被順序執行,最多會有一個任務處於活動狀態,並且不允許使用者改動線程池實例,因此可以避免其改變線程數目。
* newCachedThreadPool(),它是一種用來處理大量短時間工作任務的線程池,具有幾個鮮明特點:它會試圖緩存線程並重用,當無緩存線程可用時,就會創建新的工作線程;如果線程閑置的時間超過 60 秒,則被終止並移出緩存;長時間閑置時,這種線程池,不會消耗什么資源。其內部使用 SynchronousQueue 作為工作隊列。
* newFixedThreadPool(int nThreads),重用指定數目(nThreads)的線程,其背后使用的是無界的工作隊列,任何時候最多有 nThreads 個工作線程是活動的。這意味着,如果任務數量超過了活動隊列數目,將在工作隊列中等待空閑線程出現;如果有工作線程退出,將會有新的工作線程被創建,以補足指定的數目 nThreads。
* newSingleThreadScheduledExecutor() 創建單線程池,返回 ScheduledExecutorService,可以進行定時或周期性的工作調度。
* newScheduledThreadPool(int corePoolSize)和newSingleThreadScheduledExecutor()類似,創建的是個 ScheduledExecutorService,可以進行定時或周期性的工作調度,區別在於單一工作線程還是多個工作線程。
* newWorkStealingPool(int parallelism),這是一個經常被人忽略的線程池,Java 8 才加入這個創建方法,其內部會構建ForkJoinPool,利用Work-Stealing算法,並行地處理任務,不保證處理順序。
* ThreadPoolExecutor是最原始的線程池創建,上面1-3創建方式都是對ThreadPoolExecutor的封裝。
*
* 線程池狀態:
* private static final int RUNNING = -1 << COUNT_BITS;
* private static final int SHUTDOWN = 0 << COUNT_BITS;
* private static final int STOP = 1 << COUNT_BITS;
* private static final int TIDYING = 2 << COUNT_BITS;
* private static final int TERMINATED = 3 << COUNT_BITS;
*
* RUNNING:這個沒什么好說的,這是最正常的狀態:接受新的任務,處理等待隊列中的任務;
* SHUTDOWN:不接受新的任務提交,但是會繼續處理等待隊列中的任務;
* STOP:不接受新的任務提交,不再處理等待隊列中的任務,中斷正在執行任務的線程;
* TIDYING:所有的任務都銷毀了,workCount 為 0。線程池的狀態在轉換為 TIDYING 狀態時,會執行鈎子方法 terminated();
* TERMINATED:terminated() 方法結束后,線程池的狀態就會變成這個;
* RUNNING 定義為 -1,SHUTDOWN 定義為 0,其他的都比 0 大,所以等於 0 的時候不能提交任務,大於 0 的話,連正在執行的任務也需要中斷。
*
* 各個狀態的轉換過程有以下幾種:
*
* RUNNING -> SHUTDOWN:當調用了 shutdown() 后,會發生這個狀態轉換,這也是最重要的;
* (RUNNING or SHUTDOWN) -> STOP:當調用 shutdownNow() 后,會發生這個狀態轉換,這下要清楚 shutDown() 和 shutDownNow() 的區別了;
* SHUTDOWN -> TIDYING:當任務隊列和線程池都清空后,會由 SHUTDOWN 轉換為 TIDYING;
* STOP -> TIDYING:當任務隊列清空后,發生這個轉換;
* TIDYING -> TERMINATED:這個前面說了,當 terminated() 方法結束后;
*
*
*/
public static Map<String, ExecutorService> getPool(){
//使用Executors方式創建
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
//java8
ExecutorService workStealingPool = Executors.newWorkStealingPool();
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
//執行延遲任務
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2);
ScheduledExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
//原始創建方式
ThreadPoolExecutor tp = new ThreadPoolExecutor(10, 10, 10L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
Map<String, ExecutorService> map = new HashMap<>(7);
map.put("singleThreadExecutor", singleThreadExecutor);
map.put("cachedThreadPool", cachedThreadPool);
map.put("fixedThreadPool", fixedThreadPool);
map.put("singleThreadScheduledExecutor", singleThreadScheduledExecutor);
map.put("scheduledThreadPool", scheduledThreadPool);
map.put("workStealingPool", workStealingPool);
map.put("tp", tp);
return map;
}
}