java基礎|自定義java線程池


線程池創建的參數

在創建線程的各種方式中我們有講到過通過創建線程池來完成異步操作,但實際上jdk提供的Executors來創建線程池都還有些缺陷,線程池有以下幾個參數: 代碼節選自源碼ThreadPoolExecutor.java的構造函數

 public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize: 線程池中線程的個數,最少的個數,即使是空閑的,也會存在
maximumPoolSize: 線程池中允許的連接的最大個數
keepAliveTime: corePoolSize之外的線程,在沒有任務時,最大存活時間
unit: keepAlveTime 的時間單位
workQueue: 在任務還沒有執行前,保存Runnable任務的地方,也就是待執行任務隊列
threadFactory: 線程工廠,可自定義線程生成的方式,可以自定義名字等等
handler:在線程池和隊列滿的時候,如何處理新到來的任務

jdk自帶線程池的缺陷

自帶的線程池主要是通過Executors來初始化.

newCachedThreadPool

通過Executors.newCachedThreadPool()初始化的線程池如下文所示,可以看到maximumPoolSize的值是Integer.MAX_VALUE,這就意味着線程池里面的線程沒有上限,會一直新建到OOM.

public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}


newFixedThreadPool

通過Executors.newFixedThreadPool新建的線程池,我們可以看到workQueue這個參數傳的是new LinkedBlockingQueue,這個隊列沒有設置大小,就會導致新任務會一直往里添加,直到OOM

public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}

自定義線程池

通過對自帶的線程池的分析,我們知道自定義的線程池主要是對池子的最大數量和等待隊列的最大數量做好限制,當然還有自定義的失敗策略(以后單寫個DEMO講)代碼如下:

/**
* @author https://www.javastudy.cloud
*/
public class ThreadPoolTools {

/** 線程池維護線程的最少數量 */
private int minPoolSize = 10;

/** 線程池維護線程的最大數量 */
private int maxPoolSize = 500;

/** 線程池維護線程所允許的空閑時間 */
private int idleSeconds = 1800;

/** 線程池所使用的緩沖隊列 */
private int queueBlockSize = 100;

private ThreadPoolExecutor executor;

public ThreadPoolTools() {
this.executor = new ThreadPoolExecutor(minPoolSize, maxPoolSize, idleSeconds,
TimeUnit.SECONDS, /* 時間單位,秒 */
new ArrayBlockingQueue<Runnable>(queueBlockSize),
new ThreadPoolExecutor.CallerRunsPolicy()); /* 重試添加當前加入失敗的任務 */
}

public void execute(Runnable task) {
executor.execute(task);
}

public <T> Future<T> submit(Callable<T> task){
return executor.submit(task);
}
}



DEMO總評

線程池的使用在實際開發中用到的還是挺多的,在小型開發中使用系統自帶的線程池是沒問題的,但有時候在生產環境中,特別是同步一些東西的時候,量級比較大,這時候使用系統自帶的線程池難免會有些問題,這時候就需要自定義的線程池了,加油吧,少年!!

 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM