线程池简单的执行流程
jdk中的具体代码
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//判断小于核心线程数,并且创建线程
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//核心池已满,但任务队列未满,添加到队列中
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//队列已满,尝试创建线程
else if (!addWorker(command, false))
reject(command);
}
创建线程池的核心参数:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
corePoolSize:核心线程数,当线程数小于核心线程数,主要有新的任务进去进来,就会创建一个线程去执行任务
maximumPoolSize:最大线程数,就是当前线程池最大的线程承载量,如果线程数大于了核心线程数,并且队列满了,才会创建非核心线程外的线程去执行任务,直到线程数大于了最大线程数量,则不再创建线程,则执行拒绝策略。最大线程就是核心线程数(嫡系)+额外的线程(非核心的,相当于皇协军),但是最后创建的额外线程和核心线程是一样的,并没有什么标记,无特殊之处
keepAliveTime:核心线程外的线程存活的时间,假如某一段时段请求多,线程数都达到了最大线程数,但是过了一会,请求很少,该线程池并不需要这么多的线程,那么非核心的线程有个最大存活时间。
workQueue:阻塞队列,其实就是保存任务的容器,是个阻塞队列,就是BlockingQueue
这个BlockingQueue有很多的实现,例如ArrayBlockingQueue、DelayQueue、 LinkedBlockingDeque、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue
ArrayBlockingQueue:是个数组实现的FIFO队列
LinkedBlockingDeque:基于链表实现的FIFO队列,吞吐量高于ArrayBlockingQueue
ThreadFactory:每个线程创建的对方,可以给线程设置一些名称之类
handler:拒绝策略,当线队列满了+程数量达到最大线程数,则会使用拒绝策略,毕竟该线程池(就是个容器)总有满的时候,则可以使用一些策略保证该池子能正常运行。
包含:
AbortPolicy:新来的任务直接抛出RejectedExecutionException异常(默认使用的)
DiscardPolicy:不接收新任务,不会发出异常
DiscardOldestPolicy:把队列中最早的任务给移除了
CallerRunsPolicy:会调用当前线程池的所在的线程去执行被拒绝的任务
当然也可以自定义拒绝策略
工作中可能遇到线程池的一些问题:
1.如果使用ExecutorService创建线程池,例如创建newFixedThreadPool,里面的阻塞队列使用的无界队列LinkedBlockingQueue,因此当在线程执行任务过程中,已经超过最大线程数,则无界队列中的队列长度大小为Integer.MAX_VALUE,则可能出现内存溢出OOM;
2.如果创建的队列大小明确,但是设置的最大线程数为Integer.MAX_VALUE,当队列满了,则会一直会创建线程,这样会使服务器的CPU暴增
3.如果服务突然宕机,线程池中未执行的任务怎么办?该解决方案可以将解决任务的业务在数据中维护对应的状态,可以添加已完成,未提交等状态,然后服务重启可以创建后台一个单独线程将未执行数据的任务重新添加到线程中;