工作中经常用到线程池实现并发设计,基本都是使用的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地址