常用例子
import com.google.common.util.concurrent.ThreadFactoryBuilder;
ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("渭水-task-%d").build();
// 方法1 factory由google的common实现 主要是可以自定义线程的名字
int maximumPoolSize =Runtime.getRuntime().availableProcessors() * 4 +1;
int corePoolSize = maximumPoolSize/2;
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize,maximumPoolSize,5,TimeUnit.SECONDS
, new LinkedBlockingQueue<>(1024),factory, new ThreadPoolExecutor.AbortPolicy());
executor.allowCoreThreadTimeOut(true);
// 方法2 直接使用本地的 Executors.defaultThreadFactory()
ThreadPoolExecutor executor2 = new ThreadPoolExecutor(corePoolSize,maximumPoolSize,3,TimeUnit.SECONDS
, new LinkedBlockingQueue<>(1024), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
executor2.allowCoreThreadTimeOut(true);
上面使用的是ThreadPoolExecutor.AbortPolicy()
也就是说,当线程数已经等于maximumPoolSize,队列里也放满了,如果还submit任务,submit就会抛出异常。
参数解析
1线程池刚创建时,里面没有一个线程。任务队列是作为参数传进来的。不过,就算队列里面有任务,线程池也不会马上执行它们。
2当调用 execute() 方法添加一个任务时,线程池会做如下判断:
- 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;
- 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列。
- 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建线程运行这个任务;
- 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异常,告诉调用者“我不能再接受任务了”。
- 当一个线程完成任务时,它会从队列中取下一个任务来执行。
- 当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。
如果线程池已经满了可是还有新的任务提交怎么办?
线程池已满的定义,是指运行线程数==maximumPoolSize,并且workQueue是有界队列并且已满(如果是无界队列当然永远不会满);
在默认的 ThreadPoolExecutor.AbortPolicy 中,处理程序遭到拒绝将抛出运行时RejectedExecutionException。
在 ThreadPoolExecutor.CallerRunsPolicy 中,线程调用运行该任务的execute 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。
在 ThreadPoolExecutor.DiscardPolicy 中,不能执行的任务将被删除。
在 ThreadPoolExecutor.DiscardOldestPolicy 中,如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)
当然也可以自己实现处理策略类,继承RejectedExecutionHandler接口即可,该接口只有一个方法:
void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
参考文档
【阿里开发规范】ThreadPoolExecutor自定义线程池示例(亲测)
https://blog.csdn.net/Jack_SivenChen/article/details/53394058