This article refer to "http://ifeve.com/java-two-phase-termination/"
two-phase Termination Mode introduction
Stopping a thread is a simple, but not simple, task for a goal. First, Java does not provide a direct API for stopping threads. In addition, the stop thread has some additional details to consider, such as a stopped thread that is blocking (such as waiting for a lock) or waiting (waiting for another thread), a task that has not yet been processed, and so on.
The two-phase termination mode provides a common way to gracefully stop a thread by decomposing the stop thread into phases such as the prep phase and the execution phase.
Preparation phase
The primary action in this phase is to " notify " The target thread (the thread to be stopped) to be ready to stop . This step sets a flag variable to indicate that the target thread is ready to be stopped. However, because the target thread may be in a blocking state (waiting for a lock to be obtained), waiting state (such as Call object.wait), or I/O (such as Inputstream.read) waits, even if this flag is set, the target thread cannot immediately "see" This symbol and make the corresponding action . Therefore, this phase also needs to use the interrupt method , in order to expect the target thread to be able to detect the method call through the catch-related exception, thus interrupting its blocking state, waiting state. For methods that can respond to interrupt method calls (see table 5-1), the target thread code can detect the thread stop signal by capturing the interruptedexception thrown by these methods. However, there are some methods (such as inputstream.read) that do not respond to interrupt calls, which require us to handle manually, such as a synchronous socket I/O operation by closing the socket so that the i/ o Wait for the socket to throw java.net.SocketException.
Table 1. Some methods to respond to Thread.Interrupt
| method (or Class) |
exception thrown in response to interrupt call |
Object.wait ()? Object.wait (long timeout)? Object.wait (Long timeout, int nanos) |
Interruptedexception |
Thread.Sleep (Long Millis)? Thread.Sleep (long millis, int Nanos |
Interruptedexception |
Thread.Join ()? Thread.Join (Long Millis)? Thread.Join (Long millis, int nanos) |
Interruptedexception |
| Java.util.concurrent.BlockingQueue.take () |
Interruptedexception |
| Java.util.concurrent.locks.Lock.lockInterruptibly () |
Interruptedexception |
| Java.nio.channels.InterruptibleChannel |
Java.nio.channels.ClosedByInterruptException |
implementation phase. The main action of this phase is to check the thread stop flag and signal set during the preparation phase, on this basis, determine the timing of the thread to stop, and make the appropriate cleanup operation.
two-phase schema for termination mode
T hreadowner:The owner of the target thread. In the Java language, there is no concept of the thread owner, but the thread is behind the task it is dealing with or the service it provides, so we can't just stop it without knowing what a thread is doing. In general, we can treat the creator of the target thread as the owner of the thread and assume that it "knows" the target thread's work and can safely stop the target thread.
terminatable:You can stop the abstraction of a thread. The main methods and responsibilities are as follows
Terminate: Request the target thread to stop.
abstractterminatablethread:A thread that can be stopped. The main methods and responsibilities are as follows
Terminate:Sets the thread stop flag and sends a stop "signal" to the target thread.
doterminate: Leave yourself with some extra action that is required when the thread is stopped, such as the target thread code that contains SOCKERI/O, in which the subclass can close the socket to reach a fast stop thread without having the target thread wait for I/O completion to detect a thread stop token.
Dorun: Thread-handling logic methods. Leaves the child class with the processing logic to implement the thread. Equivalent to Thread.run (), except that the method does not need to be concerned with the logic of stopping the thread, since this logic is already encapsulated in the Terminatablethread run method.
Docleanup: Leave the subclass with some cleanup actions that may be required after the thread has been stopped.
terminationtoken:The thread stop flag. The Toshutdown is used for the target thread to stop. Reservations can be used to reflect how many unfinished tasks the target thread has yet to support before the target thread finishes processing other tasks.
Concreteterminatablethread: The implementation class of the Abstractterminatablethread participant implemented by the application itself. The class needs to implement the Dorun abstract method of its parent class, where the threading logic of the thread is implemented, and the Doterminate method, Docleanup method of its parent class is overwritten (override) according to the actual needs of the application.
Timing Diagram:
1th Step: The client code calls the thread owner's shutdown method.
2nd Step: The Shutdown method invokes the Terminate method of the target thread.
3rd, 4 steps: The Terminate method sets the Terminationtoken Toshutdown flag to True.
5th step: The Terminate method calls the Doterminate method implemented by the Abstractterminatablethread subclass so that the subclass can do some other necessary actions to stop the target thread.
6th step: If the Reservations property value of Terminationtoken is 0, the target thread does not have a task that has not been processed, or threadowner does not care if it has an unhandled task when it stops the thread. At this point, the Terminate method invokes the interrupt method of the target thread.
7th Step: Terminate method call ends
8th step: The shutdown call returns, at which point the target thread may still be running.
The execution phase is performed by the target thread's Run method to examine the value of the Terminationtoken Toshutdown property, the reservations property, and to catch the associated exception thrown by the interrupt method call to determine whether to stop the thread. The Docleanup method implemented by the Abstractterminatablethread subclass before the thread stop is called.
Two-phase Termination model actual case analysis
The alarm function of a system is encapsulated in a module. The entry class for the alarm module is alarmmgr. Other modules (business modules) need to send the alarm information only need to call Alarmmgr Sendalarm method. This method caches the alarm information such as a queue and sends an alarm by a dedicated alert sending thread responsible for invoking the Alarmagent method. The Alarmagent class is responsible for interfacing with the alarm server, which sends the alarm information to the alarm server over a network connection.
The alert send thread is a user thread, so that when the system stops, the line Chengjo does not stop and the JVM shuts down gracefully. So, we have to take the initiative to stop the alarm sending thread while the system is stopping, rather than relying on the JVM. In order to be able to gracefully stop the alarm thread as soon as possible, we need to deal with the following two questions.
1. When the alarm cache queue is not empty, it is necessary to send the alarm information in the queue to the alarm server.
2. Because the queue that caches the alarm information is a blocking queue (Arrayblockingqueue), the alert send thread will remain in a waiting state when the team is listed as empty. This causes it to fail to respond to our request to close the thread.
The above problems can be solved by using the two-phase termination mode.
"Instance view above see address"
two-phase termination