参数列表
- corePoolSize 核心线程数
- maxPoolSize 最大线程数 在这里我把(maxPoolSize和maximumPoolSize 从作用上视为一种)
- keepAliveTime 保持存活时间
- workQueue 任务存储队列
- threadFactory 当线程池需要新的线程的时候,会使用threadFactory创建新的线程
- Handler 由于线程池无法接受你所提交的任务的拒绝策略 (任务拒绝处理器)
参数说明及用法
- 当线程数小于corePoolSize 时 即使其他线程处于空闲状态 也会创建新的线程处理新的任务
- 当线程数等于(或者大于)corePoolSize 但小于 maxPoolSize 则将任务放入队列中
- 当队列满了的时候 并且线程数小于maxPoolSize 则创建新线程来运行任务
- 如果队列满了,并且线程数大于或等于maxPoolSize 则会拒绝任务
- 当突破corePoolSize时 多余的线程空闲时间超过了keepAliveTime时 那他们就会被终止
- ThreadFactory
- 默认使用的是 Executors.defaultThreadFactory(),
- 创建出来的线程都在同一个线程组
- 拥有同样的优先级5
- 不是守护线程
- 如果自己指定ThreadFactory 就可以改变线程名,线程组,优先级,是否是守护线程
- 常见的队列类型
- 直接交换: SynchronousQueue
- 用于任务不会特别多,只需要把任务通过队列进行简单的中转时
- 因为该队列是没有容量的是存不下任务的
- 如果使用该队列那maxPoolSize需要设置的大一点
- 无界队列: LinkedBlockingQueue
- 可以防治流量突增
- 但也会有OOM异常的风险
- 有界队列: ArrayBlockingQueue
- 可以设置队列容量
- 这时maxPoolSize就有意义了
- 直接交换: SynchronousQueue
- 拒绝策略
线程池的创建形式
- 手动创建 (推荐)
- 更加明确线程池的运行规则
- 避免资源耗尽的风险
- 自动创建
- newFixedThreadPool(int n) 固定数量的线程池
可能会导致OOM 因为使用的是无界队列 当处理速度赶不上请求速度时 队列会越来越多
- newFixedThreadPool(int n) 固定数量的线程池
new ThreadPoolExecutor(
nThreads, // corePoolSize
nThreads, // maxPoolSize
0L, TimeUnit.MILLISECONDS, // keepAliveTime
new LinkedBlockingQueue<Runnable>() // 用的是无界队列
);
newSingleThreadExecutor() 只有一个线程
new ThreadPoolExecutor(
1, // corePoolSize
1, // maxPoolSize
0L, TimeUnit.MILLISECONDS, // keepAliveTime
new LinkedBlockingQueue<Runnable>() // 用的是无界队列
);
newCachedThreadPool() 可缓存的线程池
当任务特别多时线程也会特别多 也会导致OOM
new ThreadPoolExecutor(
0, // corePoolSize
Integer.MAX_VALUE, // Integer 最大值
60L, TimeUnit.SECONDS, // keepAliveTime
new SynchronousQueue<Runnable>() // 用的是直接交换队列
);
newScheduledThreadPool(int corePoolSize)
threadPool.schedule(Task,延期时间,时间单位); // 延迟时间之后执行
threadPool.scheduleAtFixedRate(Task,延期时间,间隔时间,时间单位); // 延迟时间之后执行 然后每隔间隔时间循环执行
workStealingPool 1.8加入的
- 递归子任务时 使用 (树的遍历,矩阵)
- 窃取-其他线程可以处理其他子任务的队列数据
线程池数量设定
- 计算密集型的:最佳设定为CPU数量的1-2倍
- IO密集型的:一般设定大于CPU很多倍,以JVM线程监控显示繁忙情况为依据,保证线程空闲可以衔接上