问题
项目中我用线程池实现的一个数据提取功能,在生产环境报OOM,当时也是一头包,在网上乱找原因,现在做一下总结。
分析
核心参数
通过execute()方法源码可看到:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
提交优先级:核心线程->BlockingQueue队列->非核心线程
执行优先级:核心线程->非核心线程->BlockingQueue
阿里巴巴规约
Executors的静态方法:
//**newFixedThreadPool**
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
//**newSingleThreadExecutor**
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
//由于BlockingQueue的长度是Integer.MAX_VALUE,相当于可以无限制的添加任务,到一定程度会引起永久代空间不足,OOM
}
//**newCachedThreadPool**由于最大线程数是Integer.MAX_VALUE,可能会引起CPU创建很多线程,导致程序卡死
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
//**ScheduledThreadPoolExecutor**跟newCachedThreadPooll一样可能会导致程序卡死
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
队列参考文章:
BlockingQueue及其实现参考
拒绝策略
- AbortPolicy: A handler for rejected tasks that throws a RejectedExecutionException.(默认为这个拒绝策略)
- DiscardPolicy: A handler for rejected tasks that silently discards the rejected task.
- DiscardOldestPolicy: A handler for rejected tasks that discards the oldest unhandled request and then retries execute, unless the executor is shut down, in which case the task is discarded.
- CallerRunsPolicy: A handler for rejected tasks that runs the rejected task directly in the calling thread of the execute method, unless the executor has been shut down, in which case the task is discarded.
多线程下的异常捕获问题参考文章:
JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止
线程池之坑都被你踩完了我踩啥:
没想到,这么简单的线程池用法,深藏这么多坑
踏破铁鞋,学无止境,还有很长路要走。
今天一朋友生日,祝他生日快乐,写这文章顺便也希望他能好好理解线程池原理@_+ !