原理
ThreadPoolExecutor构造函数重要参数
- corePoolSize : 核心线程数线程数定义了最小可以同时运行的线程数量
- maximumPoolSize: 当队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数
- workQueue: 当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中
- keepAliveTime: 当线程池中的线程数量大于 corePoolSize 的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了 keepAliveTime才会被回收销毁
- unit: keepAliveTime 参数的时间单位
- threadFactory: executor 创建新线程的时候会用到
- handler: 饱和策略
饱和策略
- ThreadPoolExecutor.AbortPolicy: 抛出
RejectedExecutionException
来拒绝新任务的处理(默认) - ThreadPoolExecutor.CallerRunsPolicy:
调用执行自己的线程运行任务
。您不会任务请求。但是这种策略会降低对于新任务提交速度,影响程序的整体性能。另外,这个策略喜欢增加队列容量。如果您的应用程序可以承受此延迟并且你不能任务丢弃任何一个任务请求的话,你可以选择这个策略 - ThreadPoolExecutor.DiscardPolicy: 不处理新任务,
直接丢弃掉
- ThreadPoolExecutor.DiscardOldestPolicy: 此策略将
丢弃最早的未处理
的任务请求
执行原理

关于线程回收的说明
- 当线程池中的线程超过您设置的corePoolSize参数,说明当前线程池中有所谓的“非核心线程”。那么当某个线程处理完任务后,如果等待keepAliveTime时间后仍然没有新的任务分配给它,那么这个线程将会被回收。线程池回收线程时,对所谓的“核心线程”和“非核心线程”是一视同仁的,直到线程池中线程的数量等于您设置的corePoolSize参数时,回收过程才会停止
操作
基本
// 创建 并设置核心线程数,最大线程数,keepAliveTime,时间单位,等待队列类型,线程工厂,拒绝策略
ExecutorService executor = new ThreadPoolExecutor(
5,
10,
1,
TimeUnit.MINUTES,
new SynchronousQueue<Runnable>(),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
// 用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功与否
executor.execute();
// 方法用于提交需要返回值的任务
// 线程池会返回一个 Future 类型的对象,通过这个 Future 对象可以判断任务是否执行成功
// 可以通过 Future 的 get()方法来获取返回值,get()方法会阻塞当前线程直到任务完成,而使用 get(long timeout,TimeUnit unit)方法则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完
Future future = executor.submit();
// 关闭,并等待线程执行完
executor.shutdown();
// 马上关闭
executor.shutdownNow();
合理估算线程池大小
线程等待时间
所占比例越高,需要越多
线程线程CPU时间
所占比例越高,需要越少
线程- 最佳线程数目 = (线程等待时间 / 线程CPU时间 + 1)* CPU数目
- IO密集型: 2 * CPU数目(常出现于线程中:数据库数据交互、文件上传下载、网络数据传输等等)
- 计算密集型: CPU数目(常出现于线程中:复杂算法)