提出疑问
线程池使用到底要不要关闭呢?这是个哲学问题。(哈哈O(∩_∩)O哈哈~,开个玩笑,在计算机语言中只有0和1,就原理而言,和哲学没有半毛钱关系。)
代码实践
实践是检验真理的唯一标准,来,一起愉快的看代码。
线程池使用完不关闭
package ai.zixing.class04;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolShutDownTest {
public static void main(String[] args) throws IOException {
// 调用线程
newThreadPool();
// 模拟程序不停止
System.in.read();
}
private static void newThreadPool() {
// 创建一个大小为 200 个线程的线程池
ExecutorService threadPool = Executors.newFixedThreadPool(200);
for (int i = 0; i < 200; i++) {
int cur = i;
// 执行线程
threadPool.execute(
() -> System.out.print(cur)
);
}
}
}
代码有了,怎么验证呢?
打开任务管理器 ->详细信息 -> 找到 java
如果没有显示线程列的话可以右击
先看没有使用线程之前的线程数,大概是 29个
启动线程之后,显示 225 个线程
如果程序没有停止,线程是不会释放的,一直占用系统资源。
线程池使用后关闭
private static void newThreadPool() {
// 创建一个大小为 200 个线程的线程池
ExecutorService threadPool = Executors.newFixedThreadPool(200);
for (int i = 0; i < 200; i++) {
int cur = i;
// 执行线程
threadPool.execute(
() -> System.out.print(cur)
);
}
// 关闭线程池
threadPool.shutdown();
}
关闭线程池之后,在任务管理器也没查看,线程池关闭后释放线程资源。
由上面的 demo 可以得出结论,线程池用完之后需要手动调用 shutdown() 关闭线程池。真的是这样吗?继续往下看。
全局线程池使用完之后关闭
package ai.zixing.class04;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolShutDownTest {
// 创建一个大小为 200 个线程的线程池
static ExecutorService threadPool = Executors.newFixedThreadPool(200);
public static void main(String[] args) throws IOException {
// 调用线程
newThreadPool();
// 模拟程序不停止
System.in.read();
}
private static void newThreadPool() {
// 第一次调用
for (int i = 0; i < 200; i++) {
int cur = i;
// 执行线程
threadPool.execute(
() -> System.out.print(cur)
);
}
// 关闭线程池
threadPool.shutdown();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("===============================");
// 第二次调用
for (int i = 0; i < 200; i++) {
int cur = i;
// 执行线程
threadPool.execute(
() -> System.out.print(cur)
);
}
// 关闭线程池
threadPool.shutdown();
}
}
执行完之后发现线程池报错了。
总结:
综上demo实践得出结论:
1、如果是局部使用线程池,在使用完毕之后要记得执行shutdown,避免线程无法结束,造成系统资源的浪费。
2、如果是使用全局的线程池(在工作中一般是使用线程池工具类来统一管理线程池),在多个地方都有用到的线程池,不能关闭线程池,否则会抛出 java.util.concurrent.RejectedExecutionException 异常。