I'm trying to understand how threads work in Java and currently investigating how to implement looped threads that can be cancelled. Here's the code:
public static void main(String[] args) throws Exception {
Thread t = new Thread() {
#Override
public void run() {
System.out.println("THREAD: started");
try {
while(!isInterrupted()) {
System.out.printf("THREAD: working...\n");
Thread.sleep(100);
}
} catch(InterruptedException e) {
// we're interrupted on Thread.sleep(), ok
// EDIT
interrupt();
} finally {
// we've either finished normally
// or got an InterruptedException on call to Thread.sleep()
// or finished because of isInterrupted() flag
// clean-up and we're done
System.out.println("THREAD: done");
}
}
};
t.start();
Thread.sleep(500);
System.out.println("CALLER: asking to stop");
t.interrupt();
t.join();
System.out.println("CALLER: thread finished");
}
The thread I create is indended to be interrupted sooner or later. So, I check isInterrupted() flag to decide whether I need to go on and also catch InterruptedException to handle cases when I'm in a kind of waiting operation (sleep, join, wait).
Things I'd like to clarify are:
Is it fine to use interruption mechanism for this kind of task? (comparing to having volatile boolean shouldStop)
Is this solution correct?
Is it normal that I swallow InterruptedException? I'm not really interested what was the piece of code where someone asked my thread to interrupt.
Are there any shorter ways to solve this problem? (the main point is having 'infinite' loop)
EDIT
Added call to interrupt() in catch for InterruptedException.
I am answering no. 3:
Basically the question is: What purpose does an Interrupted exception have? It tells you to stop blocking (e.g. sleeping) and return early.
There are two ways dealing with an InterruptedException:
Rethrow it, so the thread remains interrupted
set Thread.currentThread.interrupt() again and do your cleanup work. This way you can be sure that another method in your thread starting to sleep will throw again
Simply swallowing an InterruptedException is not a good idea regarding the purpose of such an interrupt which is to finally terminate. But you are only asked to interrupt so you still have time to clean up.
In this case this might be an 'overreaction' of myself, but typically such code is much more complicated and how do you know, that some follow-up-code in this Thread would not call a blocking method again?
EDIT
Otherwise I think what you're doing is fine. For me a bit surprising, though, because I never saw anyone in his own code actually doing it.
And interesting article explaining why can be found here: http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html
Yes, it's fine. You should document how a Thread/Runnable must be stopped. You could add a dedicated stop method on your Runnable implementation that encapsulates the stopping mechanism. Either use interrupt, or use a dedicated boolean value, or both.
Yes, except the good practice is to restore the interrupt status when catching InterruptedException: Thread.currentThread().interrupt();
No, you should restore the interrupt status
None that I'm aware of
1) The way in your example is preferable to using a volatile flag (which is redundant since you already have the interrupted flag), according to the Java Concurrency in Practice book. It is how InterruptedExceptions were intended to be used.
2) Yes
3) you can eat the exception as long as you restore the interrupt flag status. The exception doesn't represent an error so eating it doesn't lose any information, it is purely a means of transferring control. (Restoring the interrupt flag status is important for cases where you have nested control structures that each need to be informed that the thread is cancelling, for a simple example like yours it's good form but if it's missing it won't hurt anything.)
4) no
It's fine to use Interruption, but use them well. You have to re-throw Thread.currentThread().interrupt() in your catch. Here is a piece of code showing why :
public class MyThread extends Thread {
private static boolean correct = true;
#Override
public void run() {
while (true) {
// Do Something 1
for (int i = 0; i < 10; i++) { // combined loop
// Do Something 2
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
if (correct)
Thread.currentThread().interrupt(); // reinterrupting
System.out.println("First Catch");
break; // for
}
}
try {
// Do Something 3
System.out.print("before sleep, ");
Thread.sleep(1000);
System.out.print("After sleep, ");
} catch (InterruptedException ex) {
if (correct)
Thread.currentThread().interrupt();
System.out.println("Second catch");
break; // while
}
}
System.out.println("Thread closing");
}
private static void test() throws InterruptedException {
Thread t = new MyThread();
t.start();
Thread.sleep(2500);
t.interrupt();
t.join();
System.out.println("End of Thread");
}
public static void main(String[] args)
throws InterruptedException {
test();
correct = false; // test "bad" way
test();
}
}
Another thing is, Interruptions don't always work when waiting on InputStreams. You then can use (for some) InterruptedIOException, but it won't always work. To understand these cases, you might want to try this piece of code :
public class Mythread extends Thread {
private InputStream in;
public Mythread(InputStream in) {
this.in = in;
}
#Override
public void interrupt() {
super.interrupt();
try {
in.close(); // Close stream if case interruption didn't work
} catch (IOException e) {}
}
#Override
public void run() {
try {
System.out.println("Before read");
in.read();
System.out.println("After read");
} catch (InterruptedIOException e) { // Interruption correctly handled
Thread.currentThread().interrupt();
System.out.println("Interrupted with InterruptedIOException");
} catch (IOException e) {
if (!isInterrupted()) { // Exception not coming from Interruption
e.printStackTrace();
} else { // Thread interrupted but InterruptedIOException wasn't handled for this stream
System.out.println("Interrupted");
}
}
}
public static void test1() // Test with socket
throws IOException, InterruptedException {
ServerSocket ss = new ServerSocket(4444);
Socket socket = new Socket("localhost", 4444);
Thread t = new Mythread(socket.getInputStream());
t.start();
Thread.sleep(1000);
t.interrupt();
t.join();
}
public static void test2() // Test with PipedOutputStream
throws IOException, InterruptedException {
PipedInputStream in = new PipedInputStream(new PipedOutputStream());
Thread t = new Mythread(in);
t.start();
Thread.sleep(1000);
t.interrupt();
t.join();
}
public static void main(String[] args) throws IOException, InterruptedException {
test1();
test2();
}
}
Related
I have a question about threads in Java.
I have the following code:
public static void main(String[] args) {
Runnable r = () -> {
while (!Thread.interrupted()) {
System.out.println("Hola");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println("interrupted");
break;
}
}
};
Thread t = new Thread(r);
t.start();
try {
Thread.sleep(2000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
t.interrupt();
}
Why if I introduce an interrupt does it still enter the loop? (without break).
I understand the operation of the thread when there is an exception.
Whenever the sleep method detects an interruption it resets the interrupt flag before throwing an InterruptedException. So if you don't use break then the interrupt flag is set to false by the time the exception is caught and the while loop test never detects the interruption.
The recommended practice is to add a line to your catch block like this
Thread.currentThread.interrupt();
if you want to keep the interrupt status.
It's not a problem here but be aware that Thread.interrupted() resets the interrupt flag. It's a convenience method used by some JDK code so that resetting the interrupt flag and throwing the exception takes less code.
I'm learning Java concurrency, and tried an example from Java tutorial, with a little experiment (try to catch the exception).
public class SleepMessages {
public static void main(String args[]) {
String importantInfo[] = {
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too"
};
try { // my experiment
for (int i = 0; i < importantInfo.length; i++) {
Thread.sleep(4000);
System.out.println(importantInfo[i]);
}
}
catch (InterruptedException ie) {
System.out.println("caught InterruptedException");
}
}
}
And I tried sending it an interrupt signal outside, by "kill -2 $PID".
I expected that while the processing was sleeping, the signal would cause Thread.sleep() to throw the exception, and then I could catch it, but actually not!
Could anyone explain why?
(I'm wondering maybe it's my way sending the signal (kill -2) is not correct.)
The way to handle SIGINT signals from outside, is to register a shutdown hook in your appliation:
public class Main
{
public static void main(final String[] args) throws InterruptedException
{
Runtime.getRuntime().addShutdownHook(new Thread()
{
#Override
public void run()
{
System.out.println("Shutdown hook called!");
}
});
while (true)
{
Thread.sleep(1000);
}
}
}
Now, when you start your program and kill it with kill -2 <PID> the shutdown hook will be invoked and you can gracefully shutdown.
Catching InterruptedException (what you want to do) is possible when you are interrupting your thread from inside your application using interrupt() as the following very basic example demonstrates:
public class Main
{
public static void main( final String[] args )
{
final Thread t1 = new Thread()
{
#Override
public void run()
{
try
{
while ( true )
{
Thread.sleep( 1000 );
}
}
catch ( final InterruptedException e )
{
System.out.println( "This thread was interrupted!" );
}
}
};
t1.start();
t1.interrupt();
}
}
br
InterruptedException is caught when you call Thread.interrupt() on the thread in question. It has nothing whatsoever to do with the kill program.
I tried the same scenario on my ubuntu machine, and found that when we use kill command to kill a process, then It basically kill a entire process, So this behavior is like System.exit(1), But the interrupted exception is something different, where the interrupted status flag is set to tell the thread that it has been received interrupt from some other thread, one more thing, if some other thread will interrupt this thread by calling interrupt() method on this thread instance then you will get InterruptedException only if current thread was sleeping or waiting state. If the thread is running then calling interrupt() method on it will just set the interrupt flag to true (to check interrupt status flag, you can check via isInterrupted() method on this thread instance), and will not throw InterruptedException.
See below code, here I have used System.exit(1), in a different thread, and you will see that the whole Java process was exited, there is no interrupted exception, because of the reasons explained above.
public static void main(String args[]) {
String importantInfo[] = {
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too"
};
try { // my experiment
while(true) {
Thread.sleep(4000);
Thread t = new Thread() {
public void run() {
try {
Thread.sleep(1000);
System.exit(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t.start();
System.out.println(importantInfo[0]);
}
}
catch (InterruptedException ie) {
System.out.println("caught InterruptedException");
}
}
Output of above modified code:
Mares eat oats
Process finished with exit code 1
I have a nice and compact code, which does not work as I expected.
public class Test {
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
for (;;) {
}
} finally {
System.out.println("FINALLY");
}
}
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(r);
try {
future.get(3, TimeUnit.SECONDS);
} catch (TimeoutException e) {
boolean c = future.cancel(true);
System.out.println("Timeout " + c);
} catch (InterruptedException | ExecutionException e) {
System.out.println("interrupted");
}
System.out.println("END");
}
}
The output is :
Timeout true
END
Question:
Why does not terminate the future.cancel(true) method the called Runnable?
After the program wrote the "END" to the output, the "r" Runnable is still running.
The problem is that your Runnable is not interruptible: task interruption is a collaborative process in Java and the cancelled code needs to check regularly if it's been cancelled, otherwise it won't respond to the interruption.
You can amend you code as follows and it should work as expected:
Runnable r = new Runnable() {
#Override public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {}
} finally {
System.out.println("FINALLY");
}
}
};
This is always a little bit misleading: The ExceutorService or even the underlying thread scheduler do not know anything about what the Runnable is doing. In your case they don't know that there is a unconditional loop.
All these methods (cancel, done, ...) are related to manage Threads in the Executor structure. cancel cancels the thread from the point of view of the Executor service.
The programmer must test if the Runnable was canceled and must terminate the run() method.
So in your case (if I remember well) something like this:
public class Test {
public static void main(String[] args) {
FutureTask r = new FutureTask () {
#Override
public void run() {
try {
for (;!isCancelled();) {
}
} finally {
System.out.println("FINALLY");
}
}
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(r);
try {
future.get(3, TimeUnit.SECONDS);
} catch (TimeoutException e) {
boolean c = future.cancel(true);
System.out.println("Timeout " + c);
} catch (InterruptedException | ExecutionException e) {
System.out.println("interrupted");
}
System.out.println("END");
}
}
When you cancel a Future whose Runnable has already begun, the interrupt method is called on the Thread that is running the Runnable. But that won't necessarily stop the thread. Indeed, if it's stuck in a tight loop, like the one you've got here, the Thread won't stop. In this case, the interrupt method just sets a flag called the "interrupt status", which tells the thread to stop when it can.
See the Javadoc for the interrupt method of Thread
Future.cancel() will cancel any queued task or will call Thread.interrupt() on your thread if already running.
You need to interrupt your code
It's your code's responsibility is to be ready for any interruptions. I'd go so far to say that whenever you have a long running task, that you insert some interrupt ready code like this:
while (... something long...) {
... do something long
if (Thread.interrupted()) {
... stop doing what I'm doing...
}
}
How to stop what I'm doing?
You have several options:
If your you are in Runnable.run() just return or break out of the loop and finish the method.
You may be in some other method deep in the code. It may make sense at that point for that method to throw InterruptedException so you would just do that (leaving the flag cleared).
But maybe deep in your code it doesn't make sense to throw InterruptedException. In that case you should throw some other exception, but before that mark your thread interrupted again so the code that catches knows that an interrupt was in progress. Here's an example:
private void someMethodDeepDown() {
while (.. long running task .. ) {
... do lots of work ...
if (Thread.interrupted()) {
// oh no! an interrupt!
Thread.currentThread().interrupt();
throw new SomeOtherException();
}
}
}
Now the exception can propagate an either terminate the thread or be caught, but the receiving code hopefully notices that an interrupt is in progress.
I have been looking for ways to kill a thread and it appears this is the most popular approach
public class UsingFlagToShutdownThread extends Thread {
private boolean running = true;
public void run() {
while (running) {
System.out.print(".");
System.out.flush();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {}
}
System.out.println("Shutting down thread");
}
public void shutdown() {
running = false;
}
public static void main(String[] args)
throws InterruptedException {
UsingFlagToShutdownThread t = new UsingFlagToShutdownThread();
t.start();
Thread.sleep(5000);
t.shutdown();
}
}
However, if in the while loop we spawn another another object which gets populated with data (say a gui that is running and updating) then how do we call back - especially considering this method might have been called several times so we have many threads with while (running) then changing the flag for one would change it for everyone?
thanks
One approach with these problems is to have a Monitor class which handles all the threads. It can start all necessary threads (possibly at different times/when necessary) and once you want to shutdown you can call a shutdown method there which interrupt all (or some) of the threads.
Also, actually calling a Threads interrupt() method is generally a nicer approach as then it will get out of blocking actions that throw InterruptedException (wait/sleep for example). Then it will set a flag that is already there in Threads (which can be checked with isInterrupted() or checked and cleared with interrupted(). For example the following code can replace your current code:
public class UsingFlagToShutdownThread extends Thread {
public void run() {
while (!isInterrupted()) {
System.out.print(".");
System.out.flush();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) { interrupt(); }
}
System.out.println("Shutting down thread");
}
public static void main(String[] args)
throws InterruptedException {
UsingFlagToShutdownThread t = new UsingFlagToShutdownThread();
t.start();
Thread.sleep(5000);
t.interrupt();
}
}
i added a utlility class which essentially had a static map and methods.
the map was of type Long id, Thread thread. I added two methods one to add to the map and one to stop the thread via the use of interrupt. This method took the id as a parameter.
I also changed my loop logic from while true, too while ! isInterrupted. Is this approach ok or is this bad programming style/convention
thanks
How can I notify Thread t1 and Thread t2 at the same time (so it is the same probability to get hey 1 as hey2 first)? I've tried notifyAll, but couldn't make it work.
class Thr extends Thread
{
Thr () throws InterruptedException
{
Thread t1 = new Thread() {
public synchronized void run()
{
while (true)
{
try {
wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try
{
Thread.sleep(1500);
} catch (Exception e) { }
System.out.println("hey 1");
}
}
};
Thread t2 = new Thread() {
public synchronized void run()
{
while (true)
{
try {
wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try
{
Thread.sleep(1500);
} catch (Exception e) { }
System.out.println("hey 2");
}
}
};
t1.start();
t2.start();
}
public static void main(String args[]) throws InterruptedException
{
new Thr();
}
}
You should wait on a shared object and use notifyAll as in:
class Thr extends Thread
{
Thr () throws InterruptedException
{
final Object lock = new Object ();
Thread t1 = new Thread() {
public void run()
{
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("hey 1");
}
};
Thread t2 = new Thread() {
public synchronized void run()
{
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("hey 2");
}
};
t1.start();
t2.start();
synchronized (lock) {
lock.notifyAll ();
}
}
public static void main(String args[]) throws InterruptedException
{
new Thr();
}
}
The right way to do this is to use notifyAll. The real problem with your code seems to be that you have two threads waiting for notifications on different mutexes. You need them to wait on a single object ... as described in #ShyJ's answer.
Note that there is NO WAY that you can code this so that the notification is guaranteed to be delivered first to either thread with equal probability:
The Java threading specs make no guarantees of fairness in wait / notify.
The thread scheduler implemented (typically) at the OS-level (typically) makes no such guarantees either.
The point is that the application has no control over this. The best approach is to just let wait/notifyAll do what they normally do, and design your application so that any bias in the thread scheduling does not affect the application's behaviour in an important way.
(FWIW, the usual problem is that people explicitly or implicitly assume non-randomness ... and get burned when threads get scheduled in an unexpectedly random order.)
I highly recommend avoiding the use of wait/notify and use something more robust. The problem is that using wait/notify in any combination will likely result in a race condition.
The only way to give equal probability to them academically is to create two Semaphore objects, have the threads try to acquire them, and use Random to choose which one to release first. Even then, if the scheduler decides to run the first one that tried to obtain the lock, then you get bias there anyway, regardless of whether or not the Sempahore is fair. This forces you to wait until the first thread is done before running the second, such as via Thread.join.
Bottom line, the only way to guarantee order in a concurrent system is to force them into a single-threaded format, which throws out the whole point of having them concurrent in the first place.
If you are using Java versions greater than 1.4, then it would greatly simplyfy your task by using any of the concurrent locks:
java.util.concurrent.locks specially the ReadWrite type.
For now for message passing to all the threads at the same type - implement Observer Pattern