先写结论:
shutdown不再接受新的任务,并且等待之前提交的任务都执行完再关闭,阻塞队列中的任务不会再执行。
shutdownNow直接关闭活跃状态的所有线程,并返回阻塞队列中的任务集合。
执行后线程都会被释放。
先看shutdown方法,代码如下
package com.czm.thread.testMain;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
/**
* 测试shutdown和shutdownNow
* shutdown不再接受新的任务,并且等待之前提交的任务都执行完再关闭
* shutdownNow直接关闭活跃状态的所有线程,并返回阻塞队列中的任务集合
*
* @author chengzheming
* @date 2019/1/11 11:50
*/
public class ExecutorServiceShutDownTest {
/**
* cpu核数
*/
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
/**
* 核心线程数大小
*/
private static final int corePoolSize = Math.max(2, Math.min(CPU_COUNT - 1, 4));
/**
* 线程池最大容纳线程数
*/
private static final int maximumPoolSize = CPU_COUNT * 2 + 1;
public static void main(String[] args) {
class MyThread implements Runnable {
@Override
public void run() {
try {
Random random = new Random();
//生成[1, 4)范围的随机整数
int time = random.nextInt(3) + 1;
//用于抛出异常
TimeUnit.SECONDS.sleep(time);
System.out.println(Thread.currentThread().getName() + " complete , time = " + time + "s");
} catch (InterruptedException e) {
//异常打断
System.out.println(Thread.currentThread().getName() + " Interrupted!");
}
}
}
/**
* 推荐的创建线程池的方式,自定义线程池参数。
* 核心线程数,最大线程数,线程空闲存活时间(对核心线程无效),时间单位,任务阻塞队列,任务拒绝策略
*/
ExecutorService executorService = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), new ThreadPoolExecutor.DiscardOldestPolicy());
//提交50个任务给线程池去处理
for (int i = 0; i < 50; i++) {
executorService.submit(new MyThread());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (i == 30) {
executorService.shutdown();
//返回阻塞队列中的任务集合
//List<Runnable> list = executorService.shutdownNow();
//System.out.println(list.size());
}
}
}
}
我想测试在i等于30时,shutdown是否会打断活跃的进程并不接受新线程。运行结果如下(要等一段时间程序才会停止,因为循环等待了1秒)
pool-1-thread-1 complete , time = 2s
pool-1-thread-2 complete , time = 3s
pool-1-thread-4 complete , time = 1s
pool-1-thread-3 complete , time = 3s
pool-1-thread-2 complete , time = 2s
pool-1-thread-4 complete , time = 3s
pool-1-thread-1 complete , time = 2s
pool-1-thread-3 complete , time = 3s
pool-1-thread-2 complete , time = 3s
pool-1-thread-4 complete , time = 3s
pool-1-thread-1 complete , time = 2s
pool-1-thread-3 complete , time = 2s
pool-1-thread-2 complete , time = 3s
pool-1-thread-4 complete , time = 3s
pool-1-thread-1 complete , time = 2s
pool-1-thread-2 complete , time = 2s
pool-1-thread-3 complete , time = 3s
pool-1-thread-1 complete , time = 1s
pool-1-thread-4 complete , time = 3s
pool-1-thread-2 complete , time = 1s
pool-1-thread-3 complete , time = 2s
pool-1-thread-1 complete , time = 3s
pool-1-thread-2 complete , time = 1s
pool-1-thread-4 complete , time = 3s
pool-1-thread-3 complete , time = 2s
pool-1-thread-2 complete , time = 1s
pool-1-thread-1 complete , time = 2s
pool-1-thread-4 complete , time = 1s
pool-1-thread-3 complete , time = 1s
pool-1-thread-2 complete , time = 1s
pool-1-thread-1 complete , time = 3s
Process finished with exit code 0
可以看到结果有31个任务执行完成。因为每次循环都睡眠了一秒所以没有任务在阻塞队列,因此根据结果可以推断出shutdown方法会等待活跃线程执行完再释放线程,并且不会接受新的任务执行。
那如果把循环中的TimeUnit.SECONDS.sleep(1);去掉呢,运行结果如下
pool-1-thread-4 complete , time = 1s
pool-1-thread-5 complete , time = 1s
pool-1-thread-1 complete , time = 1s
pool-1-thread-6 complete , time = 1s
pool-1-thread-9 complete , time = 1s
pool-1-thread-3 complete , time = 2s
pool-1-thread-8 complete , time = 2s
pool-1-thread-17 complete , time = 2s
pool-1-thread-14 complete , time = 2s
pool-1-thread-7 complete , time = 2s
pool-1-thread-12 complete , time = 2s
pool-1-thread-1 complete , time = 1s
pool-1-thread-6 complete , time = 1s
pool-1-thread-16 complete , time = 3s
pool-1-thread-10 complete , time = 3s
pool-1-thread-2 complete , time = 3s
pool-1-thread-13 complete , time = 3s
pool-1-thread-15 complete , time = 3s
pool-1-thread-11 complete , time = 3s
pool-1-thread-4 complete , time = 2s
pool-1-thread-14 complete , time = 1s
pool-1-thread-8 complete , time = 1s
pool-1-thread-9 complete , time = 3s
pool-1-thread-5 complete , time = 3s
pool-1-thread-17 complete , time = 2s
pool-1-thread-7 complete , time = 3s
pool-1-thread-3 complete , time = 3s
Process finished with exit code 0
这个时候阻塞队列会有任务,运行完成的任务有27个,正好是最大线程数加阻塞队列线程数,同样没有线程被打断,说明shutdown不再接受新的任务,但会执行完之前提交的任务和阻塞队列中的任务再关闭。
下面看shutdownNow,将for循环代码修改为
for (int i = 0; i < 50; i++) {
executorService.submit(new MyThread());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (i == 30) {
//executorService.shutdown();
//返回阻塞队列中的任务集合
List<Runnable> list = executorService.shutdownNow();
System.out.println(list.size());
}
}
运行结果如下
pool-1-thread-2 complete , time = 1s
pool-1-thread-1 complete , time = 3s
pool-1-thread-3 complete , time = 2s
pool-1-thread-4 complete , time = 2s
pool-1-thread-3 complete , time = 2s
pool-1-thread-2 complete , time = 2s
pool-1-thread-1 complete , time = 3s
pool-1-thread-3 complete , time = 1s
pool-1-thread-4 complete , time = 3s
pool-1-thread-2 complete , time = 2s
pool-1-thread-1 complete , time = 2s
pool-1-thread-1 complete , time = 1s
pool-1-thread-3 complete , time = 3s
pool-1-thread-2 complete , time = 3s
pool-1-thread-4 complete , time = 3s
pool-1-thread-3 complete , time = 1s
pool-1-thread-1 complete , time = 3s
pool-1-thread-2 complete , time = 2s
pool-1-thread-3 complete , time = 1s
pool-1-thread-4 complete , time = 2s
pool-1-thread-1 complete , time = 1s
pool-1-thread-1 complete , time = 2s
pool-1-thread-3 complete , time = 2s
pool-1-thread-4 complete , time = 2s
pool-1-thread-2 complete , time = 1s
pool-1-thread-1 complete , time = 1s
pool-1-thread-3 complete , time = 3s
pool-1-thread-2 complete , time = 2s
pool-1-thread-4 complete , time = 3s
pool-1-thread-1 complete , time = 1s
pool-1-thread-3 Interrupted!
0
Process finished with exit code 0
完成的任务加一条打断的线程正好31条,证明shutdownNow确实会打断活跃的线程,因为阻塞队列为空所以返回list.size()值为0。
同样将循环中TimeUnit.SECONDS.sleep(1);去掉,运行结果如下
pool-1-thread-12 Interrupted!
pool-1-thread-7 Interrupted!
pool-1-thread-1 Interrupted!
pool-1-thread-3 Interrupted!
pool-1-thread-8 Interrupted!
pool-1-thread-9 Interrupted!
pool-1-thread-5 Interrupted!
pool-1-thread-4 Interrupted!
pool-1-thread-14 Interrupted!
pool-1-thread-13 Interrupted!
pool-1-thread-2 Interrupted!
pool-1-thread-10 Interrupted!
pool-1-thread-11 Interrupted!
pool-1-thread-6 Interrupted!
10
pool-1-thread-15 Interrupted!
pool-1-thread-16 Interrupted!
pool-1-thread-17 Interrupted!
Process finished with exit code 0
有17条线程被打断了,和我设置的最大线程数一样,再次证明了shutdownNow会打断活跃线程。输出list.size()值为10,与我设置的阻塞队列长度相同,证明shutdownNow的返回值确实是阻塞线程集合。