This is a community that may be useful to you
One-to-one communication/interview brochure/resume optimization/job search questions, welcome to join the “Yudao Rapid Development Platform” Knowledge Planet. The following is some information provided by Planet:
“Project Practice (Video)”: Learn from books, “practice” from past events
“Internet High Frequency Interview Questions”: Studying with your resume, spring blossoms
“Architecture x System Design”: Overcoming difficulties and mastering high-frequency interview scenario questions
“Advancing Java Learning Guide”: systematic learning, the mainstream technology stack of the Internet
“Must-read Java Source Code Column”: Know what it is and why it is so
This is an open source project that may be useful to you
Domestic Star is a 100,000+ open source project. The front-end includes management backend + WeChat applet, and the back-end supports monomer and microservice architecture.
Functions cover RBAC permissions, SaaS multi-tenancy, data permissions, mall, payment, workflow, large-screen reports, WeChat public account, etc.:
Boot address: https://gitee.com/zhijiantianya/ruoyi-vue-pro
Cloud address: https://gitee.com/zhijiantianya/yudao-cloud
Video tutorial: https://doc.iocoder.cn
Source: juejin.cn/post/
7291564831710445622
-
1 Common scenarios that require thread exit
-
2 Graceful shutdown or forced shutdown
-
3 Ways to exit threads in other languages and Java language
-
4 Exit the thread gracefully
-
5 Summary
JDK clearly cannot forcibly destroy a thread in the thread’s Stop method, but must exit the thread gracefully.
What is meant by gracefully exiting a thread, that is, in-progress requests are correctly processed, pending requests are canceled, resource recycling is performed, and finally the Thread Runable run
method return ends execution.
First ask why you want to exit a thread, and then ask how to exit a thread
1 Common scenarios that require thread exit
-
The task execution is completed or terminates abnormally, and the task considers that it no longer needs to occupy the thread.
-
The thread pool scales the thread pool according to the current task execution status. When there are fewer tasks to perform, exit the idle thread.
-
During the shutdown phase of a service or process, such as rolling release, it is necessary to exit the thread, close the thread pool, and close the process.
-
When scheduled tasks and periodic tasks need to be terminated, the current thread needs to be exited. Or exit the execution of the current task.
In short, since you can create a thread, you will have the ability to exit a thread. There will also be scenarios where the thread exits.
There are two types of ways to close a thread: informing the thread to actively close and forcibly closing and destroying the thread.
Backend management system + user applet implemented based on Spring Boot + MyBatis Plus + Vue & Element, supporting RBAC dynamic permissions, multi-tenancy, data permissions, workflow, three-party login, payment, SMS, mall and other functions
Project address: https://github.com/YunaiV/ruoyi-vue-pro
Video tutorial: https://doc.iocoder.cn/video/
2 Graceful shutdown or forced shutdown
In fact, forcibly closing a thread has many disadvantages. If the thread is suddenly closed before the distributed lock is released, then the distributed lock cannot be released. As a result, subsequent normal lock requests fail and are blocked, affecting user bills of lading, etc. Forcibly closing a thread is tantamount to directly powering off the server.
Backend management system + user applet implemented based on Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element, supporting RBAC dynamic permissions, multi-tenancy, data permissions, workflow, three-party login, payment, SMS, mall and other functions
Project address: https://github.com/YunaiV/yudao-cloud
Video tutorial: https://doc.iocoder.cn/video/
3 Ways to exit threads in other languages and Java language
How to exit a thread in languages other than Java? In fact, every implementation has one. For example, in C++, thread execution can be forcibly terminated through ExitThread and TerminateThread. Linux not only provides the pthread_exit C language system call to forcefully close the thread, but also provides graceful exit methods such as pthread_cancel
to notify the thread to close.
Java also provides two exit methods: graceful and forced exit. However, it is clearly not recommended in the JDK to force the thread to be interrupted. In the comments of Thread.stop()
to force the thread to be interrupted, the JDK explains this
Thread.stop()
This method itself is unsafe. Stopping a thread will unlock the monitor (can be understood as a lock) held by this thread. If these monitors (locks) are blocked, ) protected critical objects are in an inconsistent state, other threads may see that these objects are in an inconsistent state, which will lead to unknown behavior. Calls toThread.Stop()
should be replaced by simple code, such as modifying a variable, checking the variable periodically by the target thread, and returning from the run method in an orderly manner. If the target thread waits on a condition variable, other threads should interrupt the target thread using the interrupt method.
In fact, closing a thread forcefully and notifying are two different concepts, that is, whether the developer of the thread task should be trusted to actively exit the thread gracefully and quickly instead of being forcibly terminated by other threads. In Java, there is only one recommended way to exit a thread, which is to exit gracefully, and the JDK also gives suggestions. By modifying variables, the target thread periodically checks the status. Or notify the target thread through interrupt.
Let’s discuss how to exit a thread gracefully?
4 Exit the thread gracefully
What are the ways?
Business field tag
Business systems often encounter requests to terminate a task. For example, there are scheduled tasks in the system. For example, after the takeout coupon package expires, the unused amount will be automatically refunded to the user. Assume that while the task is being executed, I need to redefine the input parameters of the task and terminate the task first. How to do it?
Most task codes will be processed in a loop, such as scanning the entire table to execute certain business logic. There must be a loop processing scenario, and we can determine whether the task needs to be terminated at the loop entrance. In this way, by controlling this field, we can terminate the task execution.
During specific implementation, you can control whether a certain task should be terminated through the configuration center.
while(config.isTaskEnable()) { //Get whether the task should be terminated from the configuration center //Loop to execute business logic. Exit until execution completes, or is terminated. }
This exit method tells the thread “you should exit at the appropriate time”, and the thread itself chooses to check the status at the appropriate time. Then when developers design task codes, they must design reasonable exit points in advance and check whether they need to exit at the exit point.
Thread.interrupt()
The JDK mentions that if the target thread is not in the running state, but in the blocked state, it is naturally impossible to check the exit status mark. How to notify this thread to exit?
JDK: If the target thread waits on a condition variable, other threads should interrupt the target thread using the interrupt method.
The JDK comment for interrupt mentions,
If another thread calls the interrupt method of the target thread,
-
It happens that the target thread is calling. When using
Object.wait()
,object.join ()
,Object.sleep()
, etc., the interrupt bit mark of the target thread is cleared. , and the target thread will immediately resume from sleep, wait, etc. calls, and be thrownInterruptException
. -
If the target thread is blocked during an IO operation, such as
io.channels.InterruptibleChannel
, the Channel will be closed, the thread’s interrupt bit is set, and the target thread receivesjava.nio.channels. ClosedByInterruptException
. -
If the target thread is blocked on
java.nio.channels.Selector
, the thread interrupt status is set, and then the target thread immediately returns a non-zero value from select. -
If all other conditions are not true, the thread interrupt bit will be set.
The thread interrupt bit marks whether the current thread is in an interrupted state, and the Thread.isInterrupted
method is provided to check whether the current thread is in the interrupted bit? Then why does the target thread throw an interruptException
and cancel the mark when it is blocked in the Object.wait()
, Sleep()
method? In fact, the interrupt operation performs two things, 1) setting the interrupt bit mark 2) waking up the target thread through unpark (park and unpark can block the thread and wake up the thread respectively).
However, when the target thread wakes up, it will check whether it is currently in the interrupt bit, if it is a sleep or wait operation. If it is in the interrupt bit, cancel the interrupt bit and throw an exception. The reason for canceling the middle segment should be a specification, that is, throwing an interrupt exception means that the thread is notified of the interruption, and there is no need to use the middle segment mark.
In other scenarios 2 and 3, after being awakened, the corresponding interrupt response strategies are executed respectively.
The interrupt interrupt logic is deterministic. The business thread must consider whether it has called sleep, wait or io, selector and other operations, and choose its own appropriate interrupt response strategy according to different scenarios.
So how does the recommended business thread respond to interrupts?
Recommended interrupt response strategies
Respond to interruption immediately
-
When the target thread’s task is in
InterruptedException
exception handling, it must actively recycle resources, print logs, and exit task execution. -
If the target thread has no blocking operations, such as sleep and wait. You can check the current interrupt bit status through
Thread.isInterrupted()
. If it is interrupted, take the first step above.
Ignore the interruption and leave it to the upper layer for processing
The so-called upper layer can be understood as the upper layer of the call stack. For example, the code in this layer is not responsible for handling the interrupt scenario. Then after the Interrupt exception is thrown, you can choose a solution:
-
Throw
InterruptedException
to the upper layer, which will be handled by the upper layer code. -
Call
Thread.interrupt()
. Reset the interrupt bit flag (interrupt yourself). After the method of this layer returns, the upstream code checks the interrupt bit mark and performs interrupt processing.
Of course, the most recommended way is to throw InterruptedException
, so that the upstream can perceive that there is a blockage in the downstream call chain and let the upstream process the interrupt exception.
Never swallow interrupts
What is swallowing interrupts? For example, when sleep throws InterruptedException
, it ignores the exception, does not perform any operations, and continues to execute business logic.
for (int i = 0; i < cnt; i + + ) { try { //Execute business logic Thread.sleep(10000); } catch (InterruptedException e) { System.out.println("Interrupted"); } System.out.println("Child thread is executing"); }
If handled in this way, the interrupt exception is ignored and the interrupt flag bit is also ignored. Even if the upstream method has a handling strategy for interrupts, it cannot sense the interrupt. For example, upstream calls may determine.
while(true){ callChildMethod(); //Call the downstream method, but the downstream swallowed the interrupt if (Thread.currentThread().isInterrupted()) { //Recycle resources and exit the thread } }
Some people may ask, since the upper layer can know how to handle interrupts, why don’t the developers of lower layer methods remember to throw interrupts or reset the interrupt bit?
Because there are two levels, it is probably not a developer. For example, the upper layer is a general framework code, which defines the specified logic of the task and provides extension point methods. The downstream only needs to implement extension methods. However, another developer swallowed the interrupt exception when implementing the extension point method. As a result, the framework layer had already processed the interrupt, but still could not respond to the interrupt.
Therefore, interrupt response requires upper and lower layers, and each layer of code logic needs to be considered. Even if the framework layer handles interrupt exception handling, the business logic layer must also pay attention to interrupt handling.
As a final reminder, the Thread.interrupted
method will return the current interrupt flag and cancel the interrupt bit. If you only query the interrupt bit and do not want to clean it up, you can use Thread.isInterrupted()
.
5 Summary
-
It is not recommended to forcefully destroy threads, which will result in resources not being released, in-progress requests not being processed normally, and business data being in an unknown state.
-
Java recommends exiting threads gracefully.
-
The business layer can use field tags to periodically check whether the task needs to be exited.
-
Thread.interrupt
interrupts the target thread,isInterrupted
queries the interrupt bit mark. -
Using
Thread.interrupt
to handle interrupts can also exit gracefully, but both the upper and lower stacks need to pay attention to the interrupt and must not swallow the interrupt.
Welcome to join my knowledge planet and comprehensively improve your technical capabilities.
To join, “Long press” or “Scan” the QR code below:
Planet’s content includes: project practice, interviews and recruitment, source code analysis, and learning routes.
If the article is helpful, please read it and forward it. Thank you for your support (*^__^*)
The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Java Skill TreeHomepageOverview 139421 people are learning the system