Previous Article ShutdownHook- Java elegant stop solutions need to release resources when referring to application downtime, close the connection. For some regular tasks or network service request will use the thread pool, when the correct application downtime required safety shutdown thread pool, if not handled properly, can cause data loss, the result of incorrect service request and other issues.
Close the thread pool we can choose to do nothing, naturally clears the object JVM thread pool is closed. Of course to do so, there is a serious shortcoming, thread pool threads being executed and not yet performed the task execution queue will become extremely uncontrollable. So we need to find ways to control these tasks are not performed as well as the executing thread.
Thread pool API provides two active-off method ThreadPoolExecutor#shutdownNow
with ThreadPoolExecutor#shutdown
these two methods can be used to close the thread pool, but the specific effect is not the same.
Thread pool status
Prior to said thread pool closed method, we first understand the state of the thread pool.
Thread pool state diagram as follows:
From the graph we see the thread pool are a total of five states, namely:
- The RUNNING : the initial state after the thread pool is created, this state can perform tasks.
- SHUTDOWN : The state is no longer accepting new thread pool task, but the end of the mandate will work queue.
- STOP : The state of the thread pool is no longer accepting new tasks, but will not work processing tasks in the queue, and will interrupt thread.
- TIDYING : In this state all tasks have been terminated, will be executed
terminated()
hook method. - TERMINATED : executing the
terminated()
after hook method.
When we execute ThreadPoolExecutor#shutdown
method will allow the thread pool state from RUNNING into SHUTDOWN . And call ThreadPoolExecutor#shutdownNow
after thread pool status will change from RUNNING into STOP . We can also see from the above chart, when the thread pool is in SHUTDOWN , we can continue to call the ThreadPoolExecutor#shutdownNow
method, its state to STOP .
ThreadPoolExecutor#shutdown
Above we know the thread pool status, here let us talk about shutdown
the method. shutdown
The method is relatively simple source code, which can be more intuitive understanding call logic.
shutdown
Method Source:
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 检查权限
checkShutdownAccess();
// 设置线程池状态
advanceRunState(SHUTDOWN);
// 中断空闲线程
interruptIdleWorkers();
// 钩子函数,主要用于清理一些资源
onShutdown();
} finally {
mainLock.unlock();
}
tryTerminate();
}
shutdown
Firstly lock, followed by the installation check system status. Then it will be the thread pool state to SHUTDOWN , after which the thread pool is no longer accepting new task submission. At this point if it is to continue to submit to the thread pool task, use the thread pool will reject the policy response will be used by default ThreadPoolExecutor.AbortPolicy
, throw an RejectedExecutionException
exception.
interruptIdleWorkers
The method will only interrupt the idle thread, the thread is not interrupted mission of. Idle thread will be blocked on blocking queue thread pool.
Thread pool configuration parameters you specify coresize The (core number of threads pool), maximumPoolSize (maximum number of thread pool), keepAliveTime (excess idle threads waiting time), Unit (unit of time), workQueue (blocking queue).
When the calling thread pool execute
method, the thread pool works as follows:
- If this time is less than the number of threads in the thread pool coresize The , will create a new thread to perform the task submitted.
- If this time is greater than the number of thread pool thread has coresize The , will be directly added to the task queue. Task execution thread will get from the work queue.
- If the work queue is full, we will continue to create a new thread.
- If the work queue is full, and the number of threads equal maximumPoolSize , this time will use the deny policy denies task.
- More than coreSize number of threads that part, if idle for keepAliveTime , the thread will terminate.
Workflow diagram is as follows:
When the thread pool is in the second step, the thread will be used workQueue#take
to obtain the task team head, and then complete the task. If the work has not queue tasks queue because the queue is blocked, workQueue#take
it will block the thread.
ThreadPoolExecutor#shutdownNow
ThreadPoolExecutor#shutdownNow
Source as follows:
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 检查状态
checkShutdownAccess();
// 将线程池状态变为 STOP
advanceRunState(STOP);
// 中断所有线程,包括工作线程以及空闲线程
interruptWorkers();
// 丢弃工作队列中存量任务
tasks = drainQueue();
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}
shutdownNow
The method will thread pool status to STOP , then interrupt all threads, and finally out the work queue all unfinished tasks returned to the caller.
Comparison shutdown
method, shutdownNow
method is relatively rough, direct interruption of worker threads. It should be noted, however, does not represent the end of the thread interrupt threads at once. We should actively cooperate with the thread thread interrupts.
Thread interrupt mechanism:
thread#interrupt
just set an interrupt flag, will not immediately disrupt normal thread. If you want to interrupt with immediate effect, it must be called within the threadThread.interrupted()
interrupt status judgment thread.
For the blocked thread, when calling interruption, the thread will immediately exit the blocked state and throwInterruptedException
an exception. So for blocking thread needs to correctly handleInterruptedException
exceptions.
awaitTermination
Thread Pool shutdown
and shutdownNow
methods are not actively wait for the end of the mission, if you need to wait until the end of the task execution thread pool, you need to call awaitTermination
the initiative to call the task waiting for the end.
Call as follows:
threadPool.shutdown();
try {
while (!threadPool.awaitTermination(60,TimeUnit.SECONDS)){
System.out.println("线程池任务还未执行结束");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
If the end of the thread pool task execution, awaitTermination
the method will return true
. Otherwise, when the waiting time exceeds the specified time will be returned false
.
If you need to use this band, the proposed increase must be in the basis of the above number of retries . This is really important! ! !
Elegant close the thread pool
Recalling the above thread pool state diagram, we can know in SHUTDOWN thread pool under the state still can call shutdownNow
. So we can combine shutdown
, , shutdownNow
, awaitTermination
more elegant close the thread pool.
threadPool.shutdown(); // Disable new tasks from being submitted
// 设定最大重试次数
try {
// 等待 60 s
if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
// 调用 shutdownNow 取消正在执行的任务
threadPool.shutdownNow();
// 再次等待 60 s,如果还未结束,可以再次尝试,或则直接放弃
if (!threadPool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("线程池任务未正常执行结束");
}
} catch (InterruptedException ie) {
// 重新调用 shutdownNow
threadPool.shutdownNow();
}
Article first appeared in studyidea.cn/close ..
I welcome the attention of the public number: Interpreter program, and getting daily dry push. If you are interested in my topic content, you can focus on my blog: studyidea.cn