工作中經常用到線程池實現併發設計,基本都是使用的Java自帶的線程池,寫了個簡單的demo,說明Java自帶線程池的基本原理。
ThreadPool主要有coreSize(核心線程數)、maximumSize(最大線程數)、任務隊列和線程隊列參數,這主要是因爲線程池具有動態創建線程和銷燬的特性。爲此線程池的相關參數設置:
private final int coreSize; //核心線程數
private final int maximumSize; //最大工作線程數
private final long keepAliveTime=5000; //線程的存活時間(該值從線程獲取不到工作線程開始計時)
private final BiConsumer<Runnable,ThreadPool>rejectHandler; //提交失敗的任務的處理方法
private final BlockingQueue<Runnable> requestQueue; // 任務請求隊列
private final Set<Processor> processors; //工作線程隊列
線程的創建與銷燬是根據提交的任務數量動態變化的,最重要的兩個閾值就是coreSize和maximumSize。下面對線程池的不同工作階段進行分析:
當任務數少於coreSize時
每個任務的提交,線程池都會創建一個相應的線程進行執行
當線程數等於coreSize,但是任務隊列未滿時
任務提交至任務隊列
當線程數等於coreSize,並且任務隊列已滿時
創建非核心線程處理任務
當線程數等於maximumSize
線程池不再創建工作線程,提交的任務都提交至任務隊列,如果任務隊列已滿,那麼提交的任務都會被拋棄
任務提交部分邏輯如下:
public void execute(Runnable command){
if(processors.size()<coreSize){
createProcessor(command,true);
return;
}
if(!requestQueue.offer(command)){
if(!createProcessor(command,false)){
rejectHandler.accept(command,this);
}
}
}
創建線程的邏輯
private boolean createProcessor(Runnable command,boolean isCore){
int threadThreshold=isCore?coreSize:maximumSize;
if(processors.size()>=threadThreshold)
return false;
Processor processor=new Processor(command);
processor.start();
processors.add(processor);
return true;
}
每個線程的工作代碼
private void processorRun(Processor processor){
boolean timeOut=false;
Runnable runnable=processor.initRunnable;
processor.initRunnable=null;
while (true){
try {
if(timeOut)
break;
if(runnable==null)
runnable=requestQueue.poll(keepAliveTime,TimeUnit.MILLISECONDS);
if(runnable!=null)
runnable.run();
else
timeOut=true;
}catch (InterruptedException e){
e.printStackTrace();
timeOut=true;
}
}
destroyProcessor(processor);
}
完整的線程池代碼請至我的github查看:
代碼github地址