ThreadPoolExecutor是阿里推荐的线程池。可以控制线程的数量、队列的大小等。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
}
corePoolSize: 核心线程的数量。
maximumPoolSize: 线程池最大的数量。
keepAliveTime: 空闲线程结束的超时时间(当一个线程不工作时,过keepAliveTime 长时间将停止该线程)。
unit: 表示keepAliveTime的单位。
workQueue: 放任务的队列
workQueue: 有三种类型
LinkedBlockingQueue: 链表的形式存储队列。
ArrayBlockingQueue: 数组的形式存储队列。
SynchronousQueue: 同步阻塞队列。
三者都是继承了BlockingQueue。
使用BlockingQueue最大的问题应该是StackOverflowError。
主要是涉及到了如何调节corePoolSize、maximumPoolSize、workQueue.capacity的值。
队列中最大的线程数 = maximumPoolSize + workQueue.capacity
例如:
ArrayBlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(5, true);
ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 4, 1L, TimeUnit.SECONDS, workQueue);
List<Integer> iArray = new ArrayList<>();
for (Integer i = 0; i < 9; i++) {
executor.submit(new Runnable() {
@Override
public void run() {
System.out.println("thread-id:" + Thread.currentThread().getId());
}
});
}
workQueue队列中最大的数量应该是 4 + 5 = 9.
线程创建规则:
线程先运行: thread-id:0, thread-id:1, thread-id:2
压入队列: thread-id:3, thread-id:4, thread-id:5, thread-id:6, thread-id:7
在调用线程运行: thread-id:8
先执行3个线程,然后在把后面的压入队列,如果队列满后,就再次创建线程。最大线程数量不超过maximumPoolSize,否则就会报错。