线程池的用法及思考
时间:2020-04-21
本文章向大家介绍线程池的用法及思考,主要包括线程池的用法及思考使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
本文介绍下Java中线程池的基本用法,基于此说明如何去确定线程池的大小。
线程池的创建方法
newFixedThreadPool
创建固定线程数的线程池,见下创建代码
/** * Creates a thread pool that reuses a fixed number of threads * operating off a shared unbounded queue. At any point, at most * {@code nThreads} threads will be active processing tasks. * If additional tasks are submitted when all threads are active, * they will wait in the queue until a thread is available. * If any thread terminates due to a failure during execution * prior to shutdown, a new one will take its place if needed to * execute subsequent tasks. The threads in the pool will exist * until it is explicitly {@link ExecutorService#shutdown shutdown}. * * @param nThreads the number of threads in the pool * @return the newly created thread pool * @throws IllegalArgumentException if {@code nThreads <= 0} */ public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
从代码中可发现,corePoolSize和maxPoolSize都是相等的,取决于传入的线程数,keepAliveTime=0代表线程不进行超时回收,但使用的是无界队列,当任务数量过多时,将会导致OOM溢出。
newSingleThreadPool
创建线程数为1的线程池,创建代码如下。
/** * Creates an Executor that uses a single worker thread operating * off an unbounded queue. (Note however that if this single * thread terminates due to a failure during execution prior to * shutdown, a new one will take its place if needed to execute * subsequent tasks.) Tasks are guaranteed to execute * sequentially, and no more than one task will be active at any * given time. Unlike the otherwise equivalent * {@code newFixedThreadPool(1)} the returned executor is * guaranteed not to be reconfigurable to use additional threads. * * @return the newly created single-threaded Executor */ public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); } /** * 创建线程数为1的线程池 * */
我们发现corePoolSize和MaxPoolSize都是1,使用的还是无界队列,存在OOM
newCachedThreadPool
创建可缓存的线程池。代码如下
/** * Creates a thread pool that creates new threads as needed, but * will reuse previously constructed threads when they are * available. These pools will typically improve the performance * of programs that execute many short-lived asynchronous tasks. * Calls to {@code execute} will reuse previously constructed * threads if available. If no existing thread is available, a new * thread will be created and added to the pool. Threads that have * not been used for sixty seconds are terminated and removed from * the cache. Thus, a pool that remains idle for long enough will * not consume any resources. Note that pools with similar * properties but different details (for example, timeout parameters) * may be created using {@link ThreadPoolExecutor} constructors. * * @return the newly created thread pool */ public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
从创建代码中发现,corePoolSize核心线程数在一定时间内可以为零,当有一个新的任务时,只需要创建一个存活周期为60秒的线程,使用的是直接队列,队列任务为零,当任务过多时,会创建大量的线程,仍然会导致溢出。
newScheduledThreadPool
创建定义任务相关的线程数,在普通线程池的基础上引入了定时任务相关的操作。
/** * Creates a new {@code ScheduledThreadPoolExecutor} with the * given core pool size. * * @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set * @throws IllegalArgumentException if {@code corePoolSize < 0} */ public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); }
我们发现可以指定核心线程数,maxPoolSize为Integer.MAX_VALUE,非核心线程数不进行回收,使用了延迟队列,也存在OOM
综上所述,提供了多种创建线程池的方法,具体使用哪种线程池方法,需要根据实际情况来定,使用多少线程数,最后通过性能测试去确定,我们也可以从CPU密集型和IO密集型方面进行简易区分。CPU密集型的线程数为CPU核心数的1到2倍。IO密集型线程数可为CPU核心数的10倍左右。
参考计算方法为:线程数=cpu核心数 * (1+ 平均等待时间/平均运行时间)
原文地址:https://www.cnblogs.com/cnxieyang/p/12743444.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 报错信息:(VI_1): ip address associated with VRID 80 not present in MASTER advertt : 192.168.1.8
- 如何保证集合是线程安全的? ConcurrentHashMap如何实现高效地线程安全?
- 如果MySQL的 InnoDB 文件的损坏,该如何手动恢复?
- 如何使用慢查询快速定位执行慢的 SQL?
- 如何使用 EXPLAIN 精准查看执行计划?
- MySQL怎么查看 SQL 的具体执行成本?
- Python 爬虫进阶必备 | 某外卖优惠平台内容加密参数分析
- pytest 自动化测试框架(二)
- Web | Django 与数据库交互,你需要知道的 9 个技巧
- 商机负责人与商机团队负责人不一致时更新团队负责人为商机负责人语句
- mysql常用语句集合(仅供工作日常学习参考)
- 新一代Notebook神器出现,Jupyter危险了!
- vmstat 监视内存使用情况
- Android开发重写Animation实现下拉图片后弹射回去效果示例
- Android 中RxPermissions 的使用方法详解