网站首页 > java教程 正文
专注于Java领域优质技术号,欢迎关注
作者:阿杜_javaadu
创建线程池的方式
Java中可以通过Executors和ThreadPoolExecutor的方式创建线程池,通过Executors可以快速创建四种常见的线程池,但这种方式在实际使用中并不推荐,因为这种方式创建出来的线程池可控性较差,更推荐的方式是使用ThreadPoolExecutor提供的方法。参考阿里巴巴Java开发规范:
【强制】线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更明确线程池的运行规则,规避资源耗尽的风险。说明:Executors返回的线程池对象弊端如下:1)FixedThreadPool和SingleThreadPool:允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。2)CacheThreadPool和ScheduledThreadPool:允许创建线程数量为Integer.MAX_VALUE,可能会创建大量线程,从而导致OOM。
参数的工作原理
使用ThreadPoolExecutor创建线程池需要自己给出关键的参数:
- corePoolSize:
- maximumPoolSize
- keepAliveTime
- unit
- workQueue
- threadFactory
- handler
这几大参数的工作原理如下:
图1 选自infoQ文章聊聊并发(三)
具体讲解可以参考清英在infoQ发布的文章:http://www.infoq.com/cn/articles/java-threadPool
线程池容量设置
线程池的corePoolSize设置是整个线程池中最关键的参数,设置太小会导致线程池的吞吐量不足,因为新提交的任务需要排队或者被handler处理掉(取决于拒绝策略);设置太大可能会耗尽计算机的CPU和内存资源。
CPU bound
在CS中,CPU密集型任务的执行时间主要取决于CPU的时间。CPU密集型任务的线程数通常设置为CPU核心数+1 ,《Java Concurrency in Practice》(由Doug. Lea等人撰写)给出了如下的解释:
Even compute?intensive threads occasionally take a page fault or pause for some other reason, so an"extra" runnable thread prevents CPU cycles from going unused when this happens.
即比CPU核心数多出来的一个线程是为了防止线程偶发的page fault或者由于其他原因导致的任务暂停,此时CPU就会处于空闲状态,而在这种情况下多出来的一个线程就可以充分利用CPU的这个空闲时间。
IO bound
IO密集型任务是指任务的执行时间主要取决于IO的时间。在笔者实习期间遇到的业务场景中大部分属于IO bound。而对于IO bound,书中则给出了如下的计算公式:
最佳线程数 = CPU数量 * CPU利用率 *(线程等待时间/线程CPU时间 + 1)
实际最优参数
在实际操作中,由于公式中线程等待时间和线程CPU时间不好估算,以及系统中存在其他的阻塞情况,这样计算出来的最佳线程数往往不是生产环境下的最佳线程数。为了提高精确度,笔者利用有赞内部的压测系统对代码进行压测,通过多次调整计算出来的最佳线程数和观察压测结果(系统负载、接口RT、TPS等指标)来判断线程数是否符合期望。
在压测的过程中发现,当线程数量设置的更合理时TPS更高且接口的RT较低;而线程池设置过大导致TPS下降和RT上涨。由于RT和TPS不太方便直接给出,这里仅展示系统负载这一指标的压测结果。
当线程池设置过大时:
图2 压测时把线程池参数设置得很大
当线程池设置较为合理时:
图3 线程数较为合理
原文:https://www.jianshu.com/p/47b09eafab37
猜你喜欢
- 2024-09-08 java队列之LinkedBlockingQueue和ConcurrentLinkedQueue
- 2024-09-08 Java阻塞队列中的异类,SynchronousQueue底层实现原理剖析
- 2024-09-08 100个Java工具类之61:队列类Queue
- 2024-09-08 阿里架构师浅析数据结构:队列在线程池等有限资源池中的应用
- 2024-09-08 【每日一学】Java数据结构探秘:队列与List的强大应用与性能优化
- 2024-09-08 使用Redis实现消息队列功能在Java中的应用
- 2024-09-08 『并发包入坑指北』之阻塞队列(阻塞队列poll方法)
- 2024-09-08 一文读懂,Java内置的延迟队列DelayQueue,原理及使用方法
- 2024-09-08 Java 消息队列的简单实现(java如何实现消息队列的监听)
- 2024-09-08 java 二叉树的层次遍历之队列的使用
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)