线程池的启动方式,以及线程池中的阻塞队列
1. 线程池的启动方式
newFixedThreadPool()方法:该方法返回一个固定线程池数量的线程池。该线程池中的线程数量始终不变。当有一个新的任务提交时,线程池中若有空闲的线程,则立即执行。若没有,则新的任务会被暂存到一个任务队列中,待有线程空闲时,便处理在任务队列中的任务。
newSingleThreadExecutor()方法:该方法返回一个只有一个线程的线程池。若多余一个任务被提交到线程池,任务会被保存到一个任务队列里中,待线程空闲,按先入先出的顺序执行队列中的任务。
newCachedThreadPool()方法:该方法返回一个可根据实际情况调整线程数量的线程池。线程池的数量不确定,但若有空闲可以复用,则会优先使用可复用的线程。若所有线程均在工作,又有新的任务提交,则会创建新的线程处理任务。所有线程在当前任务执行完成后,将返回线程池进行复用。
newSingleThreadSchduledExecutor() 方法:该方法返回一个ScheduledExecutorService对象,线程池的大小为1,ScheduledExecutorService接口在ExecutorService接口之上扩展了在给定时间执行某任务的功能,如在某个固定的延时之后执行,或者周期性执行某个任务。
newScheduledThreadPool()方法:该方法返回一个ScheduledExecutorService对象,但该线程池可以指定线程数量。
2. 可选择的阻塞队列BlockingQueue详解
在重复一下新任务进入时线程池的执行策略:
如果运行的线程少于corePoolSize,则 Executor始终首选添加新的线程,而不进行排队。(如果当前运行的线程小于corePoolSize,则任务根本不会存入queue中,而是直接运行)
如果运行的线程大于等于 corePoolSize,则 Executor始终首选将请求加入队列,而不添加新的线程。
如果无法将请求加入队列,则创建新的线程,除非创建此线程超出 maximumPoolSize,在这种情况下,任务将被拒绝。
主要有3种类型的BlockingQueue:
无界队列
队列大小无限制,常用的为无界的LinkedBlockingQueue,使用该队列做为阻塞队列时要尤其当心,当任务耗时较长时可能会导致大量新任务在队列中堆积最终导致OOM。阅读代码发现,Executors.newFixedThreadPool 采用就是 LinkedBlockingQueue,而楼主踩到的就是这个坑,当QPS很高,发送数据很大,大量的任务被添加到这个无界LinkedBlockingQueue 中,导致cpu和内存飙升服务器挂掉。
有界队列
常用的有两类,一类是遵循FIFO原则的队列如ArrayBlockingQueue,另一类是优先级队列如PriorityBlockingQueue。PriorityBlockingQueue中的优先级由任务的Comparator决定。
使用有界队列时队列大小需和线程池大小互相配合,线程池较小有界队列较大时可减少内存消耗,降低cpu使用率和上下文切换,但是可能会限制系统吞吐量。
在我们的修复方案中,选择的就是这个类型的队列,虽然会有部分任务被丢失,但是我们线上是排序日志搜集任务,所以对部分对丢失是可以容忍的。
同步移交队列
如果不希望任务在队列中等待而是希望将任务直接移交给工作线程,可使用SynchronousQueue作为等待队列。SynchronousQueue不是一个真正的队列,而是一种线程之间移交的机制。要将一个元素放入SynchronousQueue中,必须有另一个线程正在等待接收这个元素。只有在使用无界线程池或者有饱和策略时才建议使用该队列。
- 点赞
- 收藏
- 分享
- 文章举报
- 线程池的阻塞队列以及饱和策略处理
- 聊聊高并发(十四)理解Java中的管程,条件队列,Condition以及实现一个阻塞队列
- Windows消息队列,UI线程,窗口以及消息处理方式总结 .
- 面试-阻塞队列及线程池
- Service学习(本地服务的两种启动方式以及跨进程服务)
- Windows消息队列,UI线程,窗口以及消息处理方式总结
- Srping 一、配置启动Spring 以及 SprigBean 注册方式
- (原创)JAVA阻塞队列LinkedBlockingQueue 以及非阻塞队列ConcurrentLinkedQueue 的区别
- spring boot 项目打包jar 启动方式,以及 可能遇到的坑。
- 第四节:Task的启动的四种方式以及Task、TaskFactory的线程等待和线程延续的解决方案
- android隐藏apk方式以及apk之间的启动方式
- 线程池和阻塞队列的组合使用
- vue全家桶安装以及修改webpack配置新增vue项目启动方式
- 线程池和阻塞队列
- Java-五种线程池,四种拒绝策略,三种阻塞队列
- 线程池与阻塞队列
- 多线程以及几种启动线程的方式
- 【java基础】阻塞队列,优先级队列实现方式
- 配置Linux的eth0网卡设置IP地址以及启动方式