public class ThreadPoolExecutorTest {
private static ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS, new
ArrayBlockingQueue<>(10), new ThreadPoolExecutor.AbortPolicy());
public static void main(String[] args) throws InterruptedException {
for (int i = 1; i <= 14; i++) {
Callable<Boolean> task = createTask(i);
pool.submit(task);
System.out.println("after task:" + i + " submitted, current active count: "
+ pool.getActiveCount() + ", size of queue: " + pool.getQueue().size());
}
System.out.println("size of queue: " + pool.getQueue().size());
for (;;){
TimeUnit.SECONDS.sleep(11);
System.out.println("size of queue: " + pool.getQueue().size());
if (0 == pool.getQueue().size())
break;
}
pool.shutdown();
}
/**
* @Author Xu hao
* @Description 创建任务
* @Date 2019/3/19 0:08
* @param i
* @return java.util.concurrent.Callable
**/
private static Callable<Boolean> createTask(int i){
Callable<Boolean> callable = () -> {
TimeUnit.SECONDS.sleep(10);
System.out.println("thread: " + Thread.currentThread().getName() + " execute task: " + i);
return true;
};
return callable;
}
}
我们在上一篇文章的例子基础上每隔11秒打印一下工作队列的size,
运行结果如下:
after task:1 submitted, current active count: 1, size of queue: 0
after task:2 submitted, current active count: 2, size of queue: 0
after task:3 submitted, current active count: 2, size of queue: 1
after task:4 submitted, current active count: 2, size of queue: 2
after task:5 submitted, current active count: 2, size of queue: 3
after task:6 submitted, current active count: 2, size of queue: 4
after task:7 submitted, current active count: 2, size of queue: 5
after task:8 submitted, current active count: 2, size of queue: 6
after task:9 submitted, current active count: 2, size of queue: 7
after task:10 submitted, current active count: 2, size of queue: 8
after task:11 submitted, current active count: 2, size of queue: 9
after task:12 submitted, current active count: 2, size of queue: 10
after task:13 submitted, current active count: 3, size of queue: 10
after task:14 submitted, current active count: 4, size of queue: 10
size of queue: 10
thread: pool-1-thread-1 execute task: 1
thread: pool-1-thread-2 execute task: 2
thread: pool-1-thread-4 execute task: 14
thread: pool-1-thread-3 execute task: 13
size of queue: 6
thread: pool-1-thread-1 execute task: 3
thread: pool-1-thread-2 execute task: 4
thread: pool-1-thread-3 execute task: 6
thread: pool-1-thread-4 execute task: 5
size of queue: 2
thread: pool-1-thread-1 execute task: 7
thread: pool-1-thread-2 execute task: 8
thread: pool-1-thread-3 execute task: 9
thread: pool-1-thread-4 execute task: 10
size of queue: 0
thread: pool-1-thread-1 execute task: 11
thread: pool-1-thread-2 execute task: 12
结合上面的运行日志,来看看线程池执行的过程,
->日志前两行:线程池有两个核心线程,去执行两个任务,工作队列空闲
->日志3~12行:线程池核心线程已满,再来任务放入工作队列中
->日志13~14行:此时线程池核心线程已满,工作队列已满(放了10个任务),再来两个任务创建两个线程。(此时线程池有四个线程)
->接下来任务1 2 13 14被线程1 2 3 4执行完成
->线程池从工作队列拿出任务3 4 5 6 再去让线程1 2 3 4执行 工作队列还剩下6个任务
->线程池从工作队列拿出任务7 8 9 10 再去让线程1 2 3 4执行 工作队列还剩下2个任务
->线程池从工作队列拿出任务11 12 再去让线程1 2 执行 工作队列还剩下0个任务
->所有任务执行完成,线程池关闭
这里注意:我刚刚好提交了14个任务,如果再来一个任务,线程池已经饱和了,就会使用饱和策略来处理提交的任务,饱和策略这里我用了AbortPolicy,线程池会直接抛出异常如下
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@ca494b rejected from java.util.concurrent.ThreadPoolExecutor@1a4f24f[Running, pool size = 4, active threads = 4, queued tasks = 10, completed tasks = 0]
几种饱和策略:
读者可以每一种都去写个Demo试试看,具体使用哪种饱和策略,要结合具体的生产需求。后面我们讲线程池的合理使用会讲到。