线程笔记
1.使用线程池时,生产环境中线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式的原因:
使用Executors创建线程池有三种方式:
1.newCachedThreadPool():创建缓存线程池。
当一个任务提交时,corePoolSize为0不创建核心线程,SynchronousQueue是一个不存储元素的队列,可以理解为队里永远是满的,因此最终会创建非核心线程来执行任务。
对于非核心线程空闲60s时将被回收。因为Integer.MAX_VALUE非常大,可以认为是可以无限创建线程的,在资源有限的情况下容易引起OOM异常
源码为:
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
2.newSingleThreadExecutor():创建单线程的线程池。
当一个任务提交时,首先会创建一个核心线程来执行任务,如果超过核心线程的数量,将会放入队列中,因为LinkedBlockingQueue是长度为Integer.MAX_VALUE的队列,可以认为是无界队列,因此往队列中可以插入无限多的任务,
在资源有限的时候容易引起OOM异常,同时因为无界队列,maximumPoolSize和keepAliveTime参数将无效,压根就不会创建非核心线程
源码为:
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
3.newFixedThreadPool():创建指定线程数的线程池。
FixedThreadPool是固定核心线程的线程池,固定核心线程数由用户传入,同样是因为LinkedBlockingQueue是长度为Integer.MAX_VALUE的队列,可以认为是无界队列,容易引起OOM异常
源码为:
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
以上三种方式都是执行:new ThreadPoolExecutor(corePoolSize, maximumPoolSize,keepAliveTime, TimeUnit.MILLISECONDS,runnableTaskQueue);五个参数分别为:核心线程数,最大线程数,存活前最大空闲时间(针对非核心线程),时间单位,任务队列(等待执行任务的队列)
执行逻辑:
1.判断核心线程数是否已满,未满则创建线程执行任务 2.若核心线程池已满,判断队列是否满,若未满则加入队列中 3.若队列已满,判断线程池是否已满,若未满创建线程执行任务 4.若线程池已满,则采用拒绝策略处理无法执执行的任务
因此:建议开发者自己使用new ThreadPoolExecutor(corePoolSize, maximumPoolSize,keepAliveTime, TimeUnit.MILLISECONDS,runnableTaskQueue, threadFactory,handler);来创建线程池,这样可以根据硬件的不同来设置相对应的参数。
原文地址:https://www.cnblogs.com/zhlblogs/p/13284392.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 数组属性和方法
- PAT (Basic Level) Practice (中文)1015 德才论 (25 分)
- 前端下载二进制流文件
- element-ui 表格打印
- PAT (Basic Level) Practice (中文)1016 部分A+B (15 分)
- 【Linux_Shell 脚本编程学习笔记二、打印菜单】
- PAT (Basic Level) Practice (中文)1017 A除以B (20 分)
- git commit 提交规范
- 非常量的引用左值问题
- PAT (Basic Level) Practice (中文)1019 数字黑洞 (20 分)
- 从 12.9K 开源项目学到的新东西
- PAT (Basic Level) Practice (中文)1048 数字加密 (20 分)
- 一、类加载的双亲委托机制详解
- PAT (Basic Level) Practice (中文)1021 个位数统计 (15 分)
- PAT (Basic Level) Practice (中文)1049 数列的片段和 (20 分)
- PAT (Basic Level) Practice (中文)1022 D进制的A+B (20 分)