错误Case
工作中曾遇到过类似下面所示创建线程的代码, 这样的一个线程池其MaximumPoolSize是不会起到作用的, 因为只有当线程池中的数量大于CorePoolSize, 且缓冲队列满时才会新建线程来处理被添加的任务。而LinkedBlockingDeque队列是不会满的, 这就很容易导致任务阻塞,程序挂掉。
new ThreadPoolExecutor(1, 50, 60L, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
Executors
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
如果应用要求高负载、低延迟,最好不要选择以上两种线程池:
- 任务队列的无边界:会导致内存溢出以及高延迟 长
- 长时间运行会导致 CachedThreadPool 在线程创建上失控
因为两者都不是特别友好,所以推荐使用 ThreadPoolExecutor ,它提供了很多参数可以进行细粒度的控制。
- 将任务队列设置成有边界的队列
- 使用合适的 RejectionHandler - 自定义的 RejectionHandler 或 JDK 提供的默认 handler 。
- 重载 ThreadFactory ,如果有线程定制化的需求
- 在运行时动态控制线程池的大小(Dynamic Thread Pool)
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
new ThreadPoolExecutor(20, 100, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());