How to shut down the Java thread pool gracefully?
shutdown() method
When using the thread pool, after calling the shutdown() method, the thread pool will no longer accept new execution tasks. However, tasks placed in the task queue before calling the shutdown() method still need to be executed. This method is a non-blocking method and will return immediately after being called. It will not wait for all tasks in the task queue to be executed before returning. Let’s take a look at the source code of the shutdown() method, as shown below.
public void shutdown() { //获取线程池的全局锁 final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { //检查是否有关闭线程池的权限 checkShutdownAccess(); //将当前线程池的状态设置为SHUTDOWN advanceRunState(SHUTDOWN); //中断Worker线程 interruptIdleWorkers(); //为ScheduledThreadPoolExecutor调用钩子函数 onShutdown(); // hook for } finally { //释放线程池的全局锁 mainLock.unlock(); } //尝试将状态变为TERMINATED tryTerminate(); }
Generally speaking, the code of the shutdown() method is relatively simple. It first checks whether there is permission to close the thread pool. If there is permission, then it checks again whether there is permission to interrupt the working thread. If there is no permission, A SecurityException will be thrown, and the code is as follows.
//检查是否有关闭线程池的权限 checkShutdownAccess(); //将当前线程池的状态设置为SHUTDOWN advanceRunState(SHUTDOWN); //中断Worker线程 interruptIdleWorkers();
Among them, the implementation code of the checkShutdownAccess() method is as follows.
private void checkShutdownAccess() { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkPermission(shutdownPerm); final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { for (Worker w : workers) security.checkAccess(w.thread); } finally { mainLock.unlock(); } } }
It is relatively simple to understand the code of the checkShutdownAccess() method, which is to detect whether you have permission to close the thread pool, during which the global lock of the thread pool is used.
Next, we look at the source code of the advanceRunState(int) method, as shown below.
private void advanceRunState(int targetState) { for (;;) { int c = ctl.get(); if (runStateAtLeast(c, targetState) || ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c)))) break; } }
The overall logic of the advanceRunState(int) method is to determine whether the current thread pool state is the specified state. The state passed in the shutdown() method is SHUTDOWN. If it is SHUTDOWN, it will be returned directly; if If it is not SHUTDOWN, set the status of the current thread pool to SHUTDOWN.
Next, let’s look at the interruptIdleWorkers() method called by the showdown() method, as shown below.
private void interruptIdleWorkers() { interruptIdleWorkers(false); }
You can see that the interruptIdleWorkers() method calls the interruptIdleWorkers(boolean) method. Continue to look at the source code of the interruptIdleWorkers(boolean) method, as shown below.
private void interruptIdleWorkers(boolean onlyOne) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { for (Worker w : workers) { Thread t = w.thread; if (!t.isInterrupted() && w.tryLock()) { try { t.interrupt(); } catch (SecurityException ignore) { } finally { w.unlock(); } } if (onlyOne) break; } } finally { mainLock.unlock(); } }
The overall logic of the above code is: obtain the global lock of the thread pool, cycle through all worker threads, detect whether the thread is interrupted, if not interrupted, and the Worker thread obtains the lock, execute the thread's interruption method and release the lock acquired by the thread. At this time, if the onlyOne parameter is true, exit the loop. Otherwise, loop through all worker threads and perform the same operation. Finally, the global lock of the thread pool is released.
Next, let’s take a look at the shutdownNow() method.
shutdownNow() method
If the shutdownNow() method of the thread pool is called, the thread pool will no longer accept new execution tasks and will also discard the tasks existing in the task queue. The executing Worker thread will also be interrupted immediately. At the same time, the method will return immediately. This method has a return value, which is the list of discarded tasks in the current task queue.
The source code of the shutdownNow() method is as follows.
public List<Runnable> shutdownNow() { List<Runnable> tasks; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { //检查是否有关闭权限 checkShutdownAccess(); //设置线程池的状态为STOP advanceRunState(STOP); //中断所有的Worker线程 interruptWorkers(); //将任务队列中的任务移动到tasks集合中 tasks = drainQueue(); } finally { mainLock.unlock(); } /尝试将状态变为TERMINATED tryTerminate(); //返回tasks集合 return tasks; }
The overall logic of the source code of the shutdownNow() method is basically the same as the shutdown() method, except that the shutdownNow() method sets the status of the thread pool to STOP, interrupts all Worker threads, and puts it in the task queue All tasks are moved to the tasks collection and returned.
It can be seen that when the shutdownNow() method interrupts all threads, the interruptWorkers() method is called. Next, we will look at the source code of the interruptWorkers() method, as shown below.
private void interruptWorkers() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { for (Worker w : workers) w.interruptIfStarted(); } finally { mainLock.unlock(); } }
The logic of the interruptWorkers() method is relatively simple, which is to obtain the global lock of the thread pool, cycle through all worker threads, interrupt the threads in sequence, and finally release the global lock of the thread pool.
Inside the interruptWorkers() method, the interruptIfStarted() method of the Worker class is actually called to interrupt the thread. Let’s look at the source code of the interruptIfStarted() method of the Worker class, as shown below.
void interruptIfStarted() { Thread t; if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) { try { t.interrupt(); } catch (SecurityException ignore) { } } }
I found that it essentially calls the interrupt() method of the Thread class to interrupt the thread.
awaitTermination(long, TimeUnit) method
When the thread pool calls the awaitTermination(long, TimeUnit) method, the caller's thread will be blocked until the status of the thread pool is changed to TERMINATED. Return, or return when the timeout period is reached. Next, let's look at the source code of the awaitTermination(long, TimeUnit) method, as shown below.
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { //获取距离超时时间剩余的时长 long nanos = unit.toNanos(timeout); //获取Worker线程的的全局锁 final ReentrantLock mainLock = this.mainLock; //加锁 mainLock.lock(); try { for (;;) { //当前线程池状态为TERMINATED状态,会返回true if (runStateAtLeast(ctl.get(), TERMINATED)) return true; //达到超时时间,已超时,则返回false if (nanos <= 0) return false; //重置距离超时时间的剩余时长 nanos = termination.awaitNanos(nanos); } } finally { //释放锁 mainLock.unlock(); } }
The overall logic of the above code is: first obtain the exclusive lock of the Worker thread, and then loop to determine whether the current thread pool is already in the TERMINATED state. If so, return true directly, otherwise check whether it has timed out. If it has If it times out, it returns false. If it does not time out, reset the remaining time before the timeout. Next, enter the next cycle and check again whether the current thread pool is in the TERMINATED state. If so, return true directly. Otherwise, check whether it has timed out. If it has timed out, return false. If it does not time out, reset the remaining time before the timeout. This loop continues until the status of the thread pool becomes TERMINATED or has timed out.
The above is the detailed content of How to shut down the Java thread pool gracefully?. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

Guide to Smith Number in Java. Here we discuss the Definition, How to check smith number in Java? example with code implementation.

In this article, we have kept the most asked Java Spring Interview Questions with their detailed answers. So that you can crack the interview.

Java 8 introduces the Stream API, providing a powerful and expressive way to process data collections. However, a common question when using Stream is: How to break or return from a forEach operation? Traditional loops allow for early interruption or return, but Stream's forEach method does not directly support this method. This article will explain the reasons and explore alternative methods for implementing premature termination in Stream processing systems. Further reading: Java Stream API improvements Understand Stream forEach The forEach method is a terminal operation that performs one operation on each element in the Stream. Its design intention is

Guide to TimeStamp to Date in Java. Here we also discuss the introduction and how to convert timestamp to date in java along with examples.

Capsules are three-dimensional geometric figures, composed of a cylinder and a hemisphere at both ends. The volume of the capsule can be calculated by adding the volume of the cylinder and the volume of the hemisphere at both ends. This tutorial will discuss how to calculate the volume of a given capsule in Java using different methods. Capsule volume formula The formula for capsule volume is as follows: Capsule volume = Cylindrical volume Volume Two hemisphere volume in, r: The radius of the hemisphere. h: The height of the cylinder (excluding the hemisphere). Example 1 enter Radius = 5 units Height = 10 units Output Volume = 1570.8 cubic units explain Calculate volume using formula: Volume = π × r2 × h (4

PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHP is suitable for web development, with simple syntax and high execution efficiency. 2. Python is suitable for data science and machine learning, with concise syntax and rich libraries.

PHP is a scripting language widely used on the server side, especially suitable for web development. 1.PHP can embed HTML, process HTTP requests and responses, and supports a variety of databases. 2.PHP is used to generate dynamic web content, process form data, access databases, etc., with strong community support and open source resources. 3. PHP is an interpreted language, and the execution process includes lexical analysis, grammatical analysis, compilation and execution. 4.PHP can be combined with MySQL for advanced applications such as user registration systems. 5. When debugging PHP, you can use functions such as error_reporting() and var_dump(). 6. Optimize PHP code to use caching mechanisms, optimize database queries and use built-in functions. 7

Java is a popular programming language that can be learned by both beginners and experienced developers. This tutorial starts with basic concepts and progresses through advanced topics. After installing the Java Development Kit, you can practice programming by creating a simple "Hello, World!" program. After you understand the code, use the command prompt to compile and run the program, and "Hello, World!" will be output on the console. Learning Java starts your programming journey, and as your mastery deepens, you can create more complex applications.
