java中創建線程池的方式一般有兩種:
- 通過Executors工廠方法創建
- 通過new
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)自定義創建
Executors工廠方法創建
package com.javaBase.LineDistancePond; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * 〈一句話功能簡述〉; * 〈功能詳細描述〉 * * @author jxx * @see [相關類/方法](可選) * @since [產品/模塊版本] (可選) */ public class TestThreadPoolExecutor { public static void main(String[] args) { //創建使用單個線程的線程池 ExecutorService es1 = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { es1.submit(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "正在執行任務"); } }); } //創建使用固定線程數的線程池 ExecutorService es2 = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { es2.submit(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "正在執行任務"); } }); } //創建一個會根據需要創建新線程的線程池 ExecutorService es3 = Executors.newCachedThreadPool(); for (int i = 0; i < 20; i++) { es3.submit(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "正在執行任務"); } }); } //創建擁有固定線程數量的定時線程任務的線程池 ScheduledExecutorService es4 = Executors.newScheduledThreadPool(2); System.out.println("時間:" + System.currentTimeMillis()); for (int i = 0; i < 5; i++) { es4.schedule(new Runnable() { @Override public void run() { System.out.println("時間:"+System.currentTimeMillis()+"--"+Thread.currentThread().getName() + "正在執行任務"); } },3, TimeUnit.SECONDS); } //創建只有一個線程的定時線程任務的線程池 ScheduledExecutorService es5 = Executors.newSingleThreadScheduledExecutor(); System.out.println("時間:" + System.currentTimeMillis()); for (int i = 0; i < 5; i++) { es5.schedule(new Runnable() { @Override public void run() { System.out.println("時間:"+System.currentTimeMillis()+"--"+Thread.currentThread().getName() + "正在執行任務"); } },3, TimeUnit.SECONDS); } } }
new ThreadPoolExecutor()自定義創建
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) ;
corePoolSize:核心池的大小,這個參數跟后面講述的線程池的實現原理有非常大的關系。在創建了線程池后,默認情況下,線程池中並沒有任何線程,而是等待有任務到來才創建線程去執行任務,除非調用了prestartAllCoreThreads()或者prestartCoreThread()方法,從這2個方法的名字就可以看出,是預創建線程的意思,即在沒有任務到來之前就創建corePoolSize個線程或者一個線程。默認情況下,在創建了線程池后,線程池中的線程數為0,當有任務來之后,就會創建一個線程去執行任務,當線程池中的線程數目達到corePoolSize后,就會把到達的任務放到緩存隊列當中;
maximumPoolSize:線程池最大線程數,這個參數也是一個非常重要的參數,它表示在線程池中最多能創建多少個線程;
keepAliveTime:表示線程沒有任務執行時最多保持多久時間會終止。默認情況下,只有當線程池中的線程數大於corePoolSize時,keepAliveTime才會起作用,直到線程池中的線程數不大於corePoolSize,即當線程池中的線程數大於corePoolSize時,如果一個線程空閑的時間達到keepAliveTime,則會終止,直到線程池中的線程數不超過corePoolSize。但是如果調用了allowCoreThreadTimeOut(boolean)方法,在線程池中的線程數不大於corePoolSize時,keepAliveTime參數也會起作用,直到線程池中的線程數為0;
unit:參數keepAliveTime的時間單位,有7種取值,在TimeUnit類中有7種靜態屬性:
TimeUnit.DAYS; //天 TimeUnit.HOURS; //小時 TimeUnit.MINUTES; //分鍾 TimeUnit.SECONDS; //秒 TimeUnit.MILLISECONDS; //毫秒 TimeUnit.MICROSECONDS; //微妙 TimeUnit.NANOSECONDS; //納秒
workQueue:一個阻塞隊列,用來存儲等待執行的任務,這個參數的選擇也很重要,會對線程池的運行過程產生重大影響,一般來說,這里的阻塞隊列有以下幾種選擇:
ArrayBlockingQueue
LinkedBlockingQueue
SynchronousQueue
PriorityBlockingQueue
ArrayBlockingQueue和PriorityBlockingQueue使用較少,一般使用LinkedBlockingQueue和SynchronousQueue。線程池的排隊策略與BlockingQueue有關。
threadFactory:用於設置創建線程的工廠,可以通過線程工廠給每個創建出來的線程做些更有意義的事情,比如設置daemon和優先級等等
handler:表示當拒絕處理任務時的策略,有以下四種取值:
1、AbortPolicy:直接拋出異常。 2、CallerRunsPolicy:只用調用者所在線程來運行任務。 3、DiscardOldestPolicy:丟棄隊列里最近的一個任務,並執行當前任務。 4、DiscardPolicy:不處理,丟棄掉。 5、也可以根據應用場景需要來實現RejectedExecutionHandler接口自定義策略。如記錄日志或持久化不能處理的任務。
ThreadPoolExecutor 源碼理解
public static void test(int size) { ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(5, 20, 2, TimeUnit.SECONDS, new LinkedBlockingQueue<>(5)); for (int i = 0; i < size; i++) { poolExecutor.execute(new DemoTask(i)); Console.log("poolSize:" + poolExecutor.getPoolSize()); Console.log("corePoolSize:" + poolExecutor.getCorePoolSize()); Console.log("maximumPoolSize:" + poolExecutor.getMaximumPoolSize()); Console.log("queue:" + poolExecutor.getQueue().size()); Console.log("completedTaskCount:" + poolExecutor.getCompletedTaskCount()); Console.log("largestPoolSize:" + poolExecutor.getLargestPoolSize()); Console.log("keepAliveTime:" + poolExecutor.getKeepAliveTime(TimeUnit.SECONDS)); } poolExecutor.shutdown(); } class DemoTask implements Runnable { private int taskNum; public DemoTask(int taskNum) { this.taskNum = taskNum; } @Override public void run() { Console.log(StringUtils.center("正在執行" + taskNum, 20, "=")); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } Console.log(StringUtils.center("執行完畢" + taskNum, 20, "=")); } }
執行結果:
=======正在執行0======== poolSize:1 corePoolSize:5 maximumPoolSize:20 queue:0 completedTaskCount:0 largestPoolSize:1 keepAliveTime:2 poolSize:2 corePoolSize:5 maximumPoolSize:20 queue:0 completedTaskCount:0 =======正在執行1======== largestPoolSize:2 keepAliveTime:2 poolSize:3 corePoolSize:5 maximumPoolSize:20 =======正在執行2======== queue:0 completedTaskCount:0 largestPoolSize:3 keepAliveTime:2 poolSize:4 corePoolSize:5 maximumPoolSize:20 queue:0 =======正在執行3======== completedTaskCount:0 largestPoolSize:4 keepAliveTime:2 poolSize:5 corePoolSize:5 =======正在執行4======== maximumPoolSize:20 queue:0 completedTaskCount:0 largestPoolSize:5 keepAliveTime:2 poolSize:5 corePoolSize:5 maximumPoolSize:20 queue:1 completedTaskCount:0 largestPoolSize:5 keepAliveTime:2 poolSize:5 corePoolSize:5 maximumPoolSize:20 queue:2 completedTaskCount:0 largestPoolSize:5 keepAliveTime:2 poolSize:5 corePoolSize:5 maximumPoolSize:20 queue:3 completedTaskCount:0 largestPoolSize:5 keepAliveTime:2 poolSize:5 corePoolSize:5 maximumPoolSize:20 queue:4 completedTaskCount:0 largestPoolSize:5 keepAliveTime:2 poolSize:5 corePoolSize:5 maximumPoolSize:20 queue:5 completedTaskCount:0 largestPoolSize:5 keepAliveTime:2 poolSize:6 corePoolSize:5 maximumPoolSize:20 queue:5 completedTaskCount:0 largestPoolSize:6 keepAliveTime:2 poolSize:7 corePoolSize:5 maximumPoolSize:20 queue:5 completedTaskCount:0 largestPoolSize:7 keepAliveTime:2 =======正在執行11======= poolSize:8 corePoolSize:5 maximumPoolSize:20 queue:5 completedTaskCount:0 =======正在執行12======= =======正在執行10======= largestPoolSize:8 keepAliveTime:2 poolSize:9 corePoolSize:5 =======正在執行13======= maximumPoolSize:20 queue:5 completedTaskCount:0 largestPoolSize:9 keepAliveTime:2 poolSize:10 corePoolSize:5 maximumPoolSize:20 =======正在執行14======= queue:5 completedTaskCount:0 largestPoolSize:10 keepAliveTime:2 poolSize:11 corePoolSize:5 maximumPoolSize:20 queue:5 =======正在執行15======= completedTaskCount:0 largestPoolSize:11 keepAliveTime:2 poolSize:12 corePoolSize:5 maximumPoolSize:20 queue:5 completedTaskCount:0 =======正在執行16======= largestPoolSize:12 keepAliveTime:2 poolSize:13 corePoolSize:5 maximumPoolSize:20 =======正在執行17======= queue:5 completedTaskCount:0 largestPoolSize:13 keepAliveTime:2 poolSize:14 corePoolSize:5 maximumPoolSize:20 queue:5 =======正在執行18======= completedTaskCount:0 largestPoolSize:14 keepAliveTime:2 poolSize:15 corePoolSize:5 maximumPoolSize:20 =======正在執行19======= queue:5 completedTaskCount:0 largestPoolSize:15 keepAliveTime:2 =======執行完畢0======== =======正在執行5======== =======執行完畢1======== =======執行完畢2======== =======正在執行6======== =======正在執行7======== =======執行完畢4======== =======正在執行8======== =======執行完畢3======== =======正在執行9======== =======執行完畢13======= =======執行完畢12======= =======執行完畢10======= =======執行完畢11======= =======執行完畢15======= =======執行完畢16======= =======執行完畢14======= =======執行完畢19======= =======執行完畢18======= =======執行完畢17======= =======執行完畢5======== =======執行完畢7======== =======執行完畢6======== =======執行完畢8======== =======執行完畢9========
參考鏈接:Java線程池(一)