概述
线程池
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
- corePoolSize 核心线程数
- maximumPoolSize 最大线程数量(核心线程数+ 救济线程数 = 最大线程数)
- KeepAliveTime 救急线程最大存活时间(指的是救急线程 -当阻塞队列满的时候,创建救一定数量急线程)
- unit 时间的单位(指的是救急线程)
- workQueue 阻塞队列
- 线程工厂
- 阻塞队列已满且线程数达到最大值时所采取的拒绝策略
核心线程数多大合适?
CPU 密集型任务:
比如像加解密,压缩、计算等一系列需要大量耗费 CPU 资源的任务,大部分场景下都是纯 CPU 计算
核心线程数
= CPU核心数 + 1
IO 密集型任务:
比如像 MySQL 数据库、文件的读写、网络通信等任务,这类任务不会特别消耗 CPU 资源,但是 IO 操作比较耗时,会占用比较多时间
线程数 = CPU 核心数 * (1 + IO 耗时/ CPU 耗时)
工具类提供的线程池
-
newSingleThreadExecutor // 创建一个核心线程 newCachedThreadPool // 不创建核心线程,救急线程拉满 newSingleThreadExecutor // 创建固定数量的线程池
ps:阿里巴巴开发手册,不建议使用,让开发者创建自己了解的线程池
自定义线程工厂
可以自定义线程名称
,线程池通常都需要自定义有意义的名称
拒绝策略
顶级接口
RejectedExecutionHandler (java.util.concurrent)
- DiscardOldestPolicy //
丢掉
阻塞队列最老
的任务 - AbortPolicy // 丢弃任务,并抛出异常,
默认
的拒绝策略 - CallerRunsPolicy // 让调用者自己去执行任务,
容易
造成线程堵塞
- DiscardPolicy //
静默的抛弃任务
阻塞队列
无界队列
队列大小无限制,常用的为无界的LinkedBlockingQueue
,使用该队列做为阻塞队列时要尤其当心,当任务耗时较长时可能会导致大量新任务在队列中堆积
最终导致OOM
。Executors.newFixedThreadPool 采用就是 LinkedBlockingQueue,当QPS很高,发送数据很大,大量的任务被添加到这个无界LinkedBlockingQueue 中,导致cpu和内存飙升服务器挂掉。
有界队列
常用的有两类,一类是遵循FIFO原则的队列如ArrayBlockingQueue
与有界的LinkedBlockingQueue
,另一类是优先级队列如PriorityBlockingQueue
。PriorityBlockingQueue中的优先级由任务的Comparator决定
。
使用有界队列时队列大小需和线程池大小互相配合
,线程池较小有界队列较大时可减少内存消耗,降低cpu使用率和上下文切换,但是可能会限制系统吞吐量
,可能造成部分任务丢失
。
同步移交队列
如果不希望任务在队列中等待而是希望将任务直接移交给工作线程,可使用SynchronousQueue
作为等待队列。SynchronousQueue不是一个真正的队列,而是一种线程之间移交的机制(一手交钱、一手交货)。要将一个元素放入
,必须有另一个线程正在等待接收
这个元素。只有在使用无界线程池或者有饱和策略时才建议使用该队列。
最后
以上就是轻松自行车为你收集整理的Java线程池创建详解的全部内容,希望文章能够帮你解决Java线程池创建详解所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复