如何让线程不被销毁
文章开头说到,线程在执行完毕之后会被操作系统回收销毁,那么线程池时如何保障线程不被销毁?首先看一个测试用例:

public static void testThreadState()
 {
 Thread thread = new Thread(() -> System.out.println(“Hello world”)); // 创建一个线程
 System.out.println(thread.getState()); // 此时线程的状态为NEW
 thread.start(); // 启动线程,状态为RUNNING
 System.out.println(thread.getState());
 try
 {
 thread.join();
 System.out.println(thread.getState()); // 线程运行结束,状态为TERMINATED
 thread.start(); // 此时再启动线程会发生什么呢?
 } catch (InterruptedException e)
 {
 e.printStackTrace();
 }
 }


结果输出:

NEW
 RUNNABLE
 Hello world
 TERMINATED
 Exception in thread “main” java.lang.IllegalThreadStateException
 at java.base/java.lang.Thread.start(Thread.java:794)
 at misc.ThreadPoolExecutorTest.testThreadState(ThreadPoolExecutorTest.java:90)
 at misc.ThreadPoolExecutorTest.main(ThreadPoolExecutorTest.java:114)


可以看出,当一个线程运行结束之后,我们是不可能让线程起死回生重新启动的。既然如此ThreadPoolExecutor如何保障线程执行完一个任务不被销毁而继续执行下一个任务呢?

其实这里就要讲到我们最开始传入的参数workQueue,它的接口类型为BlockingQueue,直译过来就是阻塞队列。这中队列有个特点,就是当队列为空而尝试出队操作时会阻塞。

基于阻塞队列的如上特点,ThreadPoolExecutor采用不断循环+阻塞队列的方式来实现线程不被销毁。

final void runWorker(Worker w) {
 Thread wt = Thread.currentThread();
 Runnable task = w.firstTask;
 w.firstTask = null;
 w.unlock(); // allow interrupts
 boolean completedAbruptly = true;
 try {


// 从工作队列中不断取任务。如果工作队列为空,那么程序会阻塞在这里
while (task != null || (task = getTask()) != null) {
w.lock();
// 检查线程池状态

if ((runStateAtLeast(ctl.get(), STOP) ||
 (Thread.interrupted() &&
 runStateAtLeast(ctl.get(), STOP))) &&
 !wt.isInterrupted())
 wt.interrupt();
 try {
 beforeExecute(wt, task);
 try {
 执行任务 
 task.run();
 afterExecute(task, null);
 } catch (Throwable ex) {
 afterExecute(task, ex);
 throw ex;
 }
 } finally {
 task = null;
 w.completedTasks++;
 w.unlock();
 }
 }
 completedAbruptly = false;
 } finally {
 processWorkerExit(w, completedAbruptly);
 }
 }


关闭线程池
想要关闭线程池可以通过调用shutdown()和shutdownNow()方法实现。两种方法有所不同,其中调用shutdown()方法会停止接收新的任务,处理工作队列中的任务,调用这个方法之后线程池会进入SHUTDOWN状态,此方法无返回值并且不抛出异常。

而shutdownNow()方法会停止接收新的任务,而且会返回未完成的任务集合,同时这个方法也会抛出异常。

如何创建一个适应业务背景的线程池
线程池创建有七个参数,这几个参数的相互作用可以创建出适应特定业务场景的线程池。其中最为重要的有三个参数分别为:corePoolSize,maximumPoolSize,workQueue。其中前两个参数已经在上文中作了详细介绍,而workQueue参数在线程池创建中也极为重要。workQueue主要有三种:

SynchronousQueue:这个队列只能容纳一个元素,而且只有当队列为空时可以入队。
ArrayBlockingQueue:这是一个固定容量大小的队列。
LinkedBlockingQueue:链式阻塞队列,容量无限。
深圳网站建设www.sz886.com