JCIP-23-Executor ThreadPoolExecutor 和 Executors
ThreadPoolExecutor
线程池相关的处理时 Executor 的核心。
可以通过调用Executors以下静态工厂方法来创建线程池并返回一个ExecutorService对象。
接口定义
继承实现了 AbstractExecutorService。
AbstractExecutorService 中定义了一系列对于
public class ThreadPoolExecutor extends AbstractExecutorService {}
构造器
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) //后两个参数为可选参数
参数说明
corePoolSize:核心线程数,如果运行的线程少于corePoolSize,则创建新线程来执行新任务,即使线程池中的其他线程是空闲的
maximumPoolSize:最大线程数,可允许创建的线程数,corePoolSize和maximumPoolSize设置的边界自动调整池大小:
corePoolSize ());
}
### 例子
```java
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i ());
}
例子
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i ()));
}
FinalizableDelegatedExecutorService 是 Executors 类再次封装的一个实现,后续讲解。
暂时不做深入学习。
例子
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i ());
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
new DelayedWorkQueue());
}
所以上述两个"漏洞"在特定的场景下就有可能会导致OOM,故而很多人都不建议使用这颗"定时炸弹"。
如何正确的创建线程池?
那么上面说了使用Executors创建的线程池有隐患,那如何使用才能避免这个隐患呢?
对症下药,既然FixedThreadPool和SingleThreadPool"可能"导致的OOM是由于使用了无界队列任务堆积,CacheThreadPool和ScheduledThreadPool是由于"可能"创建Interger.MAX_VALUE,那创建线程池时我们就使用有界队列或者指定最大允许创建线程个数即可。
使用下面的构造函数
private static ExecutorService executor = new ThreadPoolExecutor(10,10,60L, TimeUnit.SECONDS,new ArrayBlockingQueue(10));
样可以指定corePoolSize、maximumPoolSize、workQueue为ArrayBlockingQueue有界队列
ThreadPoolExecutor 源码
TODO...
参考资料
《java 并发编程实战》P125
- 源码