Java线程池是java重点知识,它能够降低资源消耗,提高响应速度,在java开发中经常使用,那java线程池原理是什么?下面来我们就来给大家讲解一下java线程池原理。
1、当提交一个新任务到线程池时,线程池判断corePoolSize线程池是否都在执行任务,如果有空闲线程,则从核心线程池中取一个线程来执行任务,直到当前线程数等于corePoolSize;
2、如果当前线程数为corePoolSize,继续提交的任务被保存到阻塞队列中,等待被执行;
3、如果阻塞队列满了,那就创建新的线程执行当前任务,直到线程池中的线程数达到
maxPoolSize,这时再有任务来,由饱和策略来处理提交的任务。
java线程池队列如何选择?
workQueue - 当线程数目超过核心线程数时用于保存任务的队列。主要有3种类型的BlockingQueue可供选择:无界队列,有界队列和同步移交。从参数中可以看到,此队列仅保存实现Runnable接口的任务。
这里再重复一下新任务进入时线程池的执行策略:
当正在运行的线程小于corePoolSize,线程池会创建新的线程。
当大于corePoolSize而任务队列未满时,就会将整个任务塞入队列。
当大于corePoolSize而且任务队列满时,并且小于maximumPoolSize时,就会创建新额线程执行任务。
当大于maximumPoolSize时,会根据handler策略处理线程。
1、无界队列
队列大小无限制,常用的为无界的LinkedBlockingQueue,使用该队列作为阻塞队列时要尤其当心,当任务耗时较长时可能会导致大量新任务在队列中堆积最终导致OOM。
阅读代码发现,Executors.newFixedThreadPool 采用就是 LinkedBlockingQueue,而博主踩到的就是这个坑,当QPS很高,发送数据很大,大量的任务被添加到这个无界LinkedBlockingQueue 中,导致cpu和内存飙升服务器挂掉。
当然这种队列,maximumPoolSize 的值也就无效了。
当每个任务完全独立于其他任务,即任务执行互不影响时,适合于使用无界队列;例如,在 Web 页服务器中。
这种排队可用于处理瞬态突发请求,当命令以超过队列所能处理的平均数连续到达时,此策略允许无界线程具有增长的可能性。
2、有界队列
当使用有限的 maximumPoolSizes 时,有界队列有助于防止资源耗尽,但是可能较难调整和控制。
常用的有两类,一类是遵循FIFO原则的队列如ArrayBlockingQueue,另一类是优先级队列如PriorityBlockingQueue。
PriorityBlockingQueue中的优先级由任务的Comparator决定。
使用有界队列时队列大小需和线程池大小互相配合,线程池较小有界队列较大时可减少内存消耗,降低cpu使用率和上下文切换,但是可能会限制系统吞吐量。
3、同步移交队列
如果不希望任务在队列中等待而是希望将任务直接移交给工作线程,可使用SynchronousQueue作为等待队列。
SynchronousQueue不是一个真正的队列,而是一种线程之间移交的机制。要将一个元素放入SynchronousQueue中,必须有另一个线程正在等待接收这个元素。
当然只有在使用无界线程池或者有饱和策略时才建议使用该队列。另外,java线程池能够提高线程的可管理性,使线程池可以进行统一分配、调优和监控,最后大家如果想要了解更多java入门知识,敬请关注奇Q工具网。
推荐阅读: