In Java, it is easy to write multi-threaded programs for thread class. However, in front of programmers, multithreading presents a set of new problems, and if there is no proper solution, it will lead to unexpected behavior and subtle, difficult to discover errors. In this article, we are for these problems: how to interrupt a running thread.
background
Interrupt (Interrupt) A thread means it stopping its current operation before the thread completes the task, effectively aborts its current operation. The thread is death, or waiting for a new task or continues to run to the next step, depending on this program.
Although it seems that it may seem simple, you have to make some warning to achieve the desired result. Do you better keep in mind the following advice.
First, forget the thread.stop method. Although it does stop a running thread, this method is unsafe to advocate, which means that in future Java versions, it will not exist.
Some tight guys may be confused by another method Thread.Interrupt. Although, its name seems to be implied, however, this method does not break a running thread (will further explain further), as described in Listing A. It creates a thread and tries to stop the thread using the Thread.Iterrupt method. The call of the thread.sleep () method provides a bad time for the initialization and abortment of threads. Thread itself does not participate in any useful operation.
Listing a
Class example1 extends thread {
Public static void main (string args []) throws exception {
Example1 thread = new example1 ();
System.out.println ("Starting Thread ...");
Thread.start ();
Thread.sleep (3000);
System.out.Println ("Interrupting Thread ...");
Thread.Iterrupt ();
Thread.sleep (3000);
System.out.println ("Stopping Application ...");
System.exit (0);
}
If you run the code in Listing A, you will see the following output in the console:
Starting thread ...
Thread is Running ...
Thread is Running ...
Thread is Running ...
Interrupting Thread ...
Thread is Running ...
Thread is Running ...
Thread is Running ...
STOPPING Application ...
Even after thread.interrupt () is called, the thread continues to run for a while.
Truely interrupt a thread
The best way to interrupt the thread is the most recommended way to send a signal using a shared variable, telling the thread to stop running the task. The thread must verify this variable (especially during redundant operation) and then suspend tasks in order. Listing B describes this.
Listing B
Class example2 extends thread {
Volatile Boolean Stop = False;
Public static void main (string args []) throws exception {example2 thread = new example2 ();
System.out.println ("Starting Thread ...");
Thread.start ();
Thread.sleep (3000);
System.out.println ("Asking Thread to stop ...");
Thread.stop = true;
Thread.sleep (3000);
System.out.println ("Stopping Application ...");
System.exit (0);
}
Public void run () {
While (! stop) {
System.out.println ("Thread Is Running ...");
Long Time = system.currenttimemillis ();
While ((System.CurrentTimeMillis () - TIME <1000) && (! stop) {
}
}
System.out.println ("Thread Exiting Under Request ...");
}
}
The code running in Listing B will produce the following output (note how the thread is exit)
Starting thread ...
Thread is Running ...
Thread is Running ...
Thread is Running ...
Ask thread to stop ...
Thread EXITING Under Request ...
STOPPING Application ...
Although this method requires some encoding, it is not difficult to achieve. At the same time, it gives thread opportunities for the necessary cleanup work, which is absolutely needed in any multi-thread application. Confirm that the shared variable is defined as a Volatile type or will be enclosed in the Synchronized Blocks / Methods for all of its access to the Synchronization.
Everything goes well until now! However, what happens when the thread waits some events? Of course, if the thread is blocked, it cannot verify the shared variable, and it will not stop. This happens in many cases, such as call Object.Wait (), serversocket.accept () and DataGramsocket.Receive (), only some.
They may have a permanent blocking thread. Even if the timeout is timeout, it is not feasible and inappropriate before the time period is full, so it is necessary to use a certain mechanism to exit the blocked state earlier.
It is very unfun, there is no such mechanism to apply for all the cases, but according to the situation, specific technologies can be used. In the following link, I will answer the most common example.
Using Thread.Iterrupt () interrupt thread
As described in Listing A, the Thread.Iterrupt () method does not interrupt a running thread. This method is actually completed, and an interrupt signal is thrown when the thread is blocked, so that the thread is to exit the blockage. More specifically, if the thread is blocked by one of the three methods of object.wait, thread.join, and thread.sleep, then it will receive an interrupt exception (interruptexception), so that it will end the blocked state early.
Therefore, if the thread is blocked by the above methods, the correct stop thread is to set the shared variable and call Interrupt () (note that the variable should be set first). If the thread is not blocked, the interrupt () will not work at this time; otherwise, the thread will be exception (this thread must be prepared in advance), then escape the blocking state. In either case, the last thread will check the shared variable and then stop. Listing C This example describes the technology.
Listing C
Class Example3 Extends Thread {
Volatile Boolean Stop = False;
Public static void main (string args []) throws exception {
EXAMPLE3 thread = new example3 ();
System.out.println ("Starting Thread ...");
Thread.start ();
Thread.sleep (3000);
System.out.println ("Asking Thread to stop ...");
Thread.stop = true;
Thread.Iterrupt ();
Thread.sleep (3000);
System.out.println ("Stopping Application ...");
System.exit (0);
}
Public void run () {
While (! stop) {
System.out.Println ("Thread Running ...");
Try {
Thread.sleep (1000);
} catch (interruptedexception e) {
System.out.println ("Thread Interrupted ...");
}
}
System.out.println ("Thread Exiting Under Request ...");
}
}
Once the thread.interrupt () in Listing C is called, the thread receives an exception, so that the blocking state is escaped and determines that should be stopped. Run the above code will get the following output:
Starting thread ...
Thread Running ...
Thread Running ...
Thread Running ...
Ask thread to stop ...
Thread Interrupted ...
Thread EXITING Under Request ...
STOPPING Application ...
Interrupt I / O operation
However, if the thread is blocked when I / O operation is performed, what will be? I / O operations can block the thread a quite long, especially when it is involved in the network application. For example, the server may need to wait for a request, or, a network application may wait for the response of the remote host.
If you are using channel (Channels) (this is the new I / O API introduced in Java 1.4), the blocked thread will receive a ClosedByInterrupTexception exception. If this is the case, the logic of its code is the same in the third example, but it is only unusual.
However, you may be using traditional I / O before Java 1.0, because the new I / O is only introduced recently, and more work is required. In this case, thread.interrupt () will not work because the thread will not exit the blocked state. Listing D describes this line. Although interrupt () is called, the thread does not exit the blocked state Listing D.
Import java.io. *;
Class example4 extends thread {
Public static void main (string args []) throws exception {
EXAMPLE4 THREAD = New Example4 ();
System.out.println ("Starting Thread ...");
Thread.start ();
Thread.sleep (3000);
System.out.Println ("Interrupting Thread ...");
Thread.Iterrupt ();
Thread.sleep (3000);
System.out.println ("Stopping Application ...");
System.exit (0);
}
Public void run () {
ServerSocket Socket;
Try {
Socket = New Serversocket (7856);
} catch (ioexception e) {
System.out.Println ("Could Not Create The Socket ...");
Return;
}
While (true) {
System.out.println ("Waiting for Connection ...");
Try {
Socket Sock = Socket.accept ();
} catch (ioexception e) {
System.out.println ("Accept () failed or interrupted ...");
}
}
}
}
Fortunately, the Java platform provides a solution to this situation, that is, call the close () method of the socket that blocks the thread. In this case, if the thread is blocked by the I / O operation, the thread will receive a socketException exception, which is very similar to an interruptException exception in using an interrupt () method.
The only thing to explain is that there must be a reference to the Socket, and only this close () method can be called. This means that the Socket object must be shared. Listing E describes this situation. Running logic and previous examples are the same.
Listing E
Import java.net. *;
Import java.io. *;
Class Example5 Extends Thread {
Volatile Boolean Stop = False;
Volatile Serversocket Socket;
Public static void main (string args []) throws exception {
EXAMPLE5 THREAD = New Example5 ();
System.out.println ("Starting Thread ...");
Thread.start ();
Thread.sleep (3000);
System.out.println ("Asking Thread to Stop ..."); thread.stop = true;
thread.socket.close ();
Thread.sleep (3000);
System.out.println ("Stopping Application ...");
System.exit (0);
}
Public void run () {
Try {
Socket = New Serversocket (7856);
} catch (ioexception e) {
System.out.Println ("Could Not Create The Socket ...");
Return;
}
While (! stop) {
System.out.println ("Waiting for Connection ...");
Try {
Socket Sock = Socket.accept ();
} catch (ioexception e) {
System.out.println ("Accept () failed or interrupted ...");
}
}
System.out.println ("Thread Exiting Under Request ...");
}
}
The following is the output after running the code in Listing E:
Starting thread ...
Waiting for Connection ...
Ask thread to stop ...
Accept () failed or interrupted ...
Thread EXITING Under Request ...
STOPPING Application ...
Multithreading is a powerful tool, however it is presenting a series of puzzles. One of them is how to interrupt a running thread. If properly implemented, interrupt the thread using the above technology will be more simple than the embedded operation already provided on the Java platform.