is Thread.sleep() guaranteed to wait? - java

Consider this scenario:
I want to make several web service calls consecutively. I am only allowed to make a call every 10 seconds. I have something like this:
while(true) //we will break inside the loop eventually
{
//...
try {
Thread.sleep(10000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
//make web service call here
//...
}
As you can see, This will (hopefully) make a call approximately every 10 seconds. But my concern is that while Thread.sleep() is executing, I will get interrupted before 10 seconds and I will subsequently make a web service call that will get ignored.
This is not a multithreaded application so it runs on its own JVM. This is the only thread I am not calling interrupt() on this thread from anywhere, but I am not sure if I will run into trouble with my host machine's thread scheduler or anything.
Accuracy of timekeeping is not of great importance. I especially don't care if the 10 seconds turns into 15 seconds. But if somehow Thread.Sleep throws too soon I will be in trouble.
Is this the proper way of implementing this behaviour?
To clarify:
1- this is NOT a multi-threaded program
2- I do NOT want to do a exact times, the timing can be inaccurate as long as an unexpected exception does not get me out of the try block prematurely

I am not sure if I will run into trouble with my host machine's thread scheduler
No, the runtime will not interrupt an application thread for any reason. Only other code in your application (or code that you drag in with some framework that you choose) will interrupt threads.
Every task should specify an interruption policy: what will happen if the thread is interrupted? An application should never interrupt a thread without understanding its interrupt policy and being prepared to deal with the consequences.
So, define the interrupt policy for your thread. In your application, it is something you don't expect to happen, and if someone adds code to your application that calls interrupt() on your thread, they introduced a bug. Basically, your policy is that interruption isn't allowed. So, throwing a some unchecked exception, like IllegalStateException is a valid response.
Is this the proper way of implementing this behaviour?
No, it's not. When you are interrupted, you should signal callers that you were interrupted. This should be done by letting an InterruptedException propagate back to the caller (or a application-defined exception with similar meaning), or by restoring the interrupt status on the current thread. Suppose your interruption policy permits interruption, by terminating the loop prematurely. You should still restore the interrupt status:
while(true) {
...
try {
Thread.sleep(10000);
} catch(InterruptedException abort) {
Thread.currentThread().interrupt();
break;
}
/* Make web service call here... */
}

No, it is not guaranteed to wait for at least 10 seconds. The whole point of the sleep method throwing the checked exception InterruptedException is the possible need to end the sleep before the 10 seconds are up, by interrupting the thread.
You are wrong to focus on your program being "single threaded". In practice there is no such thing: the JVM and the JRE are permitted (and in fact do) run additional threads. The Thread.sleep() API says that the method throws InterruptedException if the sleeping thread is interrupted by another thread; it does not specify that only "user" threads are permitted to interrupt the sleeping thread.

Related

Why are methods after interruption of a thread not called?

I would like to shutdown a thread gracefully. However, once the shutdown is initiated the thread should perform some shutdown operation after ending usual operation.
Both threads use sleeps and/or wait and handle InterruptedException, they also work on tasks in a loop taking only a few milliseconds. So that I expected the while loop to end because Thread.currentThread().isInterrupted() becomes "true".
The problem is that with my code sometimes I get the log "SHUTDOWN" and sometimes not. Also I get "INTERRUPTED" only sometimes, which I understand of course. With another similar thread I never get the "SHUTDOWN".
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(new Test());
Thread.sleep(10000);
executor.shutdown();
try {
if(this.executor.awaitTermination(60, TimeUnit.SECONDS)) {
this.loggerFactory.getLogger(this.getClass()).info("CLOSED (GRACEFULLY)!");
} else {
this.executor.shutdownNow();
this.loggerFactory.getLogger(this.getClass()).info("CLOSED (IMMEDIATELY)!");
}
} catch(InterruptedException e) {
this.executor.shutdownNow();
this.loggerFactory.getLogger(this.getClass()).info("CLOSED (IMMEDIATELY)!");
}
class Test implements Runnable {
private volatile boolean isRunning = true;
#Override
public void run() {
try {
while(!Thread.currentThread().isInterrupted()) {
while(!this.isRunning) {
synchronized(this) {
this.wait();
}
}
// DO SOMETHING LASTING A FEW MILLISECONDS
Thread.sleep(500);
}
} catch(InterruptedException e) {
this.loggerFactory.getLogger(this.getClass()).info("INTERRUPTED!");
}
this.loggerFactory.getLogger(this.getClass()).info("SHUTDOWN!");
// DO SOME SHUTDOWN OPERATION
}
}
EDIT:
After some commentary by OP, an entirely different and much superior solution seems to be available:
Use hooks!
Java has a system to 'install' a shutdown hook. These are called when the VM shuts down... sometimes. If you get SIGTERMed (kill -9) or someone trips over a powercable, or linux kills your process due to excessive memory use, or the kernel dumps, or your VM hard crashes (for example, a core dump in native code), or the device loses power, they don't get called, of course.
But, if someone in the process runs System.exit(), or all non-daemon threads are done, or someone hits CTRL+C or sends SIGKILL (kill, not kill -9) to your process, they get run first, and only when they all finish does the java process actually end.
That sounds like a vastly superior solution here. Your shutdown hook should:
acquire the lock on some private AtomicBoolean.
set the boolean to false (the boolean indicates: May I query this sensor?)
release the lock.
reset the sensor.
return.
And all your normal operation code that reads that sensor should:
acquire a lock on the boolean.
if false, throw or otherwise abort.
perform the sensor read operation.
release the lock.
Nothing should ever touch that sensor without holding the lock (failure to do this would imply maybe messing with that sensor after you've already reset it, which would be bad).
original answer:
I would like to shutdown a thread gracefully.
Why? 'gracefully' is a very nice sounding word, but once you dig into what it means, it's just nasty things. It's a word that means: "That will cause my software to fail, possibly persistently (as in, won't start anymore without cleaning up stuff), if someone trips over a powercable or my app hard-crashes".
A much better design is to have a thread that doesn't need to be shut down. Just pull the plug on it, and all is well.
For example, old filesystems (MS-DOS and early windows age) required graceful shutdowns; failure to do so would lead to persistent issues - the system wouldn't boot at all, you bricked the box. They then had mitigation systems in place (chkdsk systems), but modern OSes are much better. Their filesystem handling setup mostly doesn't care about being 'gracefully' shut down. Just pull the plug on em, they'll be fine, that's what journals do.
So that I expected the while loop to end because Thread.currentThread().isInterrupted() becomes "true".
That's not how you're supposed to use that API.
Here's the basic gist of what the interrupted API does:
Any thread can 'raise the interrupt flag' on any other (someThread.interrupt()).
raising the flag doesn't do anything other than raise the flag, unless a method explicitly decides to look at it.
The method Thread.interrupted() is how you're supposed to read the flag out in order to act upon it, __and not Thread.currentThread().isInterrupted(). The former will check the flag and clear it. The latter merely checks the flag.
Some java methods are specced to respond to the flag being up. You recognize these methods because they throws InterruptedException. There may be more methods; for example, on most OSes, interrupting a thread currently waiting for more bytes to flow in from the network (they are blocked on a read() call on an InputStream obtained from socket.getInputStream()) WILL cause that read call to fail (with an IOException, not an InterruptedException, because read() isn't specced to throw InterruptedEx), but that's no guarantee; on some OSes, it won't, and you can't interrupted that.
The general policy is that the moment you handle an interrupted flag, you lower the flag, and java code does just that: If a method throws InterruptedEx, the flag will be cleared.
Java does not define what you should do if interrupted. Threads don't get magically interrupted; for example, when your VM shuts down (someone hits CTRL+C), that doesn't interrupt any threads whatsoever. Java will just 'pull the plug' on all threads. That's because this is better (see above). Therefore, if a thread is interrupted, that's because you wrote thread.interrupt() someplace, therefore, you decide what it means. Maybe it means 're-read a config file and restart the server listening process'. Maybe it means 'stop calculating chess moves and perform the best move found so far'. Maybe it means 'recheck for a condition'. Maybe it means 'end the thread entirely'. It's up to you. There is no standard.
Note that the various methods specced to respond to interrupt flags (such as wait(): It throws InterruptedException) all share this property: If you call them while the flag is up, they will instantly return by throwing InterruptedException, they never even begin waiting.
So, for your code, given that you wait() already, just make that while(true) and rely on the InterruptedEx.

What is an InterruptedException in Java?

I have seen many times in my code that I get an Interrupted Exception. How do I fix it?
Example:
for (int i = 0; i < readLimit; i++) {
if (fileName.exists())
return readFile(fileName);
Thread.sleep(1000); // Here is where I get the error
}
}
Since I don't know how much you know about Java, how java works exactly and what's concurrency, I'll try to explain as much as possible with nearly no background information needed.
At first we're going to take a look at Oracle's documentation of the InterruptedException.
Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is interrupted, either before or during the activity. [...]
What does this mean?
Before answering this question you have to rudimentary understand how a Thread works.
A thread is originally just a piece of code that can be managed seperately from other threads. It can run at the same time (see concurrency), run scheduled, etc.
Example
If you start a normal java program the main() method is created in an own thread 1. Everything you do will be executed in this thread. Every class you create, every method you call and basically everything that originated from main().
But if you create a Thread, it runs in an own thread 2. Everything you do in the run() method will be executed in thread 2.
What happens if you create a new Thread?
The join() method is called.
The join() method starts the thread and run() is being executed.
There's not only the join() method with no parameters but also a join(long millis) with a parameter.
When and why is it thrown?
As Rahul Iyer already said there's a variety of reasons. I'm picking some of them to get you a feeling when they're called.
Timeout
The InterruptedException can be indeed thrown when a timeout was exceeded. This happens when the join(long millis) is called. The parameter specifies that the thread can run for the given amount of milliseconds. When the thread exceeds this timeout it is interrupted. source (from line 769 to line 822).
OS is stopping the thread
Maybe the Operating System (Windows, Linux, Android, etc.) decided to stop the program. Why? To free resources, your program was mistaken as a virus, hardware is shutting down, the user manually closed it, etc.
An InterruptedException is thrown in the Thread
For example you're connected to the internet and you're reading something and the internet disconnects suddenly.
interrupt() is called
As already mentioned, an InterruptedException is also thrown, when you call the interrupt() on any Thread (quite logical).
How to handle it?
You can/should handle it like every other exception. Wrap it in a try and catch, declare that the method throws it, log it, etc.
This may be the best resource for you: Handling InterruptedException in Java.
From the docs: https://docs.oracle.com/javase/7/docs/api/java/lang/InterruptedException.html
public class InterruptedException extends Exception
Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is
interrupted, either before or during the activity. Occasionally a
method may wish to test whether the current thread has been
interrupted, and if so, to immediately throw this exception. The
following code can be used to achieve this effect:
if (Thread.interrupted()) // Clears interrupted status!
throw new InterruptedException();
You can follow oracles tutorial here:
https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
The way to fix it is probably to surround the code that causes it with a Try-Catch block and handle the exception. For example (from Oracles tutorial):
for (int i = 0; i < importantInfo.length; i++) {
// Pause for 4 seconds
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
// We've been interrupted: no more messages.
return;
}
// Print a message
System.out.println(importantInfo[i]);
}
There are more examples in the above link on how to handle different scenarios.
Shortly, InterruptedException is usually thrown when a thread or some other action is interrupted. It does not matter if the thread was doing something or sleeping, you can programmatically do this by calling interrupt() or other methods on and "occupied" thread, who is for sleeping.

Stopping/Interrupting a thread after time limit

I have an application which uses a third party jar to do some task. My application uses Spring Executor pool to spawn the threads.
Question:
I need to stop the current execution of a thread if the executing time exceeds the time limit
What I did:
I googled a lot about interrupting thread. Most of says to check the interrupt flag whether the thread is interrupted or not and if interrupted throw an interrupted exception. But in thread I'm calling a method which is in a third party jar which do most of the stuffs so I can't go there and change the code for checking the interrupt flag.
Consider the following code snippet:
public void run() {
boolean isDone = false;
isDone = callThirdPartyMethod(); // here for some inputs thread takes more time (even never return for an hour!!) to process which I don't want and I need to stop/interrupt the thread
}
Approaches I follow for stopping/interrupting it
I had wrote a TimerTask which checks for the thread which is
exceeding the time limit and call the interrupt() on them (but it
seems nothing happens as they continue their execution).
I changed the code of my TimerTask from interrupting it to calling
the stop() on thread. This works but it throws ThreadDeath error.
Also what I read in most of the blogs and even in stackoverflow is
that we should never call the stop method.
Question: I need to stop the current execution of a thread if the executing time exceeds the time limit
There is no easy answer here. Typically you create one thread to make the third party library call and one thread to watch the clock and kill the other thread when a timer expires.
You can call interrupt the third party library thread but as you mention there is no guarantee that callThirdPartyMethod() will listen for the interrupt. You can call stop() but this is deprecated for good reasons.
The only addition mechanism is to close something that the third party library is using. Maybe a socket or other connection could be closes out from under the library.
If there is not way to do it then thread.stop() is your only (unfortunate) alternative unless you can get at the source of the library.
Otherwise you are SOL unfortunately.

How can I immediately terminate a Thread? (Not interrupt)

This is not a question about how to cleanly terminate a thread, ie by calling interrupt on it and having the thread respond appropriately. I cannot modify code the thread is executing in any way.
I specifically want to immediately terminate a Thread, I don't care at all what state things are left in. I know something similar is possible using Thread.stop, however this actually throws a ThreadDeath exception, and for the Thread to terminate this exception cannot be caught. However the code I am dealing with catches this exception and is not rethrowing it.
Thread.destroy() seemed to be what I was looking for, however this method was never implemented. Is there any other way of achieving this?
I believe that there's no way in Java to just kill off a thread like you're describing. As you note in a comment, interrupt won't do what you want. If the thread is executing, it just sets a flag and it's up to the thread to notice it. if the thread is waiting or sleeping, it will throw an InterruptedException.
The only way I can imagine doing what you're describing is to kill the process in which the thread is running. (E.g., call System.exit(int).)
No there isn't a way. From Java Concurrency in Practice:
Since there is no preemptive way to stop a thread, they must instead
be persuaded to shut down on their own.
Interrupting a thread is not the cleaner way as you said. Clean ways could be:
ExecutorService.shutdown()
Future.cancel()
Poison Pills
You aren't meant to submit tasks to threads that take ages to be done. You would rather divide them into smaller tasks and send a poison pill to cancel the bigger task. If there is not a way to do that, then spawn/fork a process and kill it if you want to cancel the task.
If you don't trust the thread in question to the point that you need to kill it, you would probably be better off running it in a separate process, and kill the process instead.
Anyway, the following code might work if you are ok with the deprecated Thread methods:
while (theThread.isAlive()) {
theThread.stop();
}
Depending on how badly the thread is trying to surviveā€¦
You might want to run this code in several threads or repeat the stop() call if that's not enough. However, I managed to kill the following thread with this code:
final Thread iWontDie = new Thread(() -> {
int i = 0;
while (true) {
try {
System.out.println("I'm still alive! " + ++i);
} catch (Throwable t) {
// eat t
}
}
});
iWontDie.start();
If you are on Java 7 or earlier, you could use the overloaded stop(Throwable obj) method to throw something besides a ThreadDeath error:
Forces the thread to stop executing. If the argument obj is null, a NullPointerException is thrown (in the current thread). The thread represented by this thread is forced to stop whatever it is doing abnormally and to throw the Throwable object obj as an exception. This is an unusual action to take; normally, the stop method that takes no arguments should be used.
This method, like the parameterless version, is deprecated, so just keep that in mind.

Handling InterruptedException while waiting for an exit signal (bug in Android?)

I've come across the code below, and I'm wondering if it does exactly what I think it does:
synchronized(sObject) {
mShouldExit = true;
sObject.notifyAll()
while (!mExited) {
try {
sObject.wait();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
About the context: there is another thread that checks for mShouldExit (inside the sObject monitor) and will exit in that case.
This does not look to be a correct pattern to me. If an interrupt happens, it will set the interrupted status again, so when it returns to sObject.wait(), another InterruptedException will come etc. etc. etc. Therefore, it can never go to truly waiting state (sObject.wait()) i.e. it will never release the sObject monitor. This may result in an infinite loop, as the other thread cannot set mExiting to true, because it can never enter sObject's monitor. (So I think that the interrupt() call is an error, it must not be used here.) Am I missing something?
Note that the code snippet is a part of the official Android framework source code.
UPDATE: actually, the situation is worse, because the same pattern is used in Android when your GL rendering starts. The official source code of GLSurfaceView.GLThread.surfaceCreated():
public void surfaceCreated() {
synchronized(sGLThreadManager) {
if (LOG_THREADS) {
Log.i("GLThread", "surfaceCreated tid=" + getId());
}
mHasSurface = true;
sGLThreadManager.notifyAll();
while((mWaitingForSurface) && (!mExited)) {
try {
sGLThreadManager.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
You can reproduce the bug in a similar way: make sure your UI thread has its interrupted status flag yet, then add your GLSurfaceView and start the GL rendering (via setRenderer(...), but on some devices, make sure your GLSurfaceView has Visibility.VISIBLE status, otherwise rendering will not start).
If you follow the above steps, your UI thread will end up in an infinite loop, because the above-quoted code will keep generating an InterruptedException (due to wait()) and therefore the GL thread will never be able to set mWaitingForSurface to false.
According to my tests, it seems that such an infinite loop will also result in an endless sequence of GC_CONCURRENT garbage collection (or, at least, such messages in logcat). Interesting, someone had an unknown poorly-defined issue on stackoverflow earlier which might be related:
How to solve GC_concurrent freed?
Isn't it possible that perhaps his UI thread had its interrupted flag set to true, and he was using a GLSurfaceView for the map he mentions? Just an assumption, a possible scenario.
Short version: That code is wrong, and will cause an infinite loop (I still have a doubt, but may depend on JVM implementations). Setting the interrupt status is the right thing to do, but it should then exit the loop, eventually checking that same interruption status using Thread.isInterrupted().
Long version for the casual reader:
The problem is how to stop a thread that is currently executing some work, in response to a "Cancel" button from the user or because of some other application logic.
Initially, Java supported a "stop" method, that preemptively stopped a thread. This method has been demonstrated to be unsafe, cause didn't give the stopped thread any (easy) way to clean up, release resources, avoid exposing partially modified objects and so on.
So, Java evolved to a "cooperative" Thread "interruption" system. This system is quite simple : a Thread is running, someone else calls "interrupt" on it, a flag is set on the Thread, it's Thread responsibility to check if it has been interrupted or not and act accordingly.
So, correct Thread.run (or Runnable.run, of Callable etc..) method implementation should be something like :
public void run() {
while (!Thread.getCurrentThread().isInterrupted()) {
// Do your work here
// Eventually check isInterrupted again before long running computations
}
// clean up and return
}
This is fine as long as all the code your Thread is executing is inside your run method, and you never call something that blocks for a long time ... which is often not the case, cause if you spawn a Thread is because you have something long to do.
The simplest method that block is Thread.sleep(millis), it's actually the only thing it does : it blocks the thread for the given amount of time.
Now, if the interrupt arrives while your thread is inside Thread.sleep(600000000), without any other suport, it would take a lot for it to arrive to the point where it checks isInterrupted.
There are even situations where your thread would never exit. For example, your thread is computing something and sending results to a BlockingQueue with a limited size, you call queue.put(myresult), it will block until the consumer free some space in the queue, if in the mean time the consumer has been interrupted (or died or whatever), that space will never arrive, the method will not return, the check on .isInterrupted will never be performed, your thread is stuck.
To avoid this situation, all (most) methods that interrupt the thread (should) throw InterruptedException. That exception simply tells you "I was waiting for this and that, but in the meanwhile the thread as been interrupted, you should do cleanup and exit as soon as possible".
As with all exceptions, unless you know what to do, you should re-throw it and hope that someone above you in the call stack knows.
InterruptedExceptions are even worse, since when they are thrown the "interrupted status" is cleared. This means that simply catching and ignoring them will result in a thread that usually does not stop :
public void run() {
while (!Thread.getCurrentThread().isInterrupted()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// Nothing here
}
}
}
In this example, if the interrupt arrives during the sleep() method (which is 99.9999999999% of the time), it will throw InterruptedException, clear the interrupt flag, then the loop will continue since the interrupt flag is false, and the thread will not stop.
That's why if you implement your "while" correctly, using .isInterrupted, and you really need to catch InterruptedException, and you don't have anything special (like cleanup, return etc..) to do with it, least that you can do is set the interrupt flag again.
The problem in the code you posted is that the "while" relies solely on mExited to decide when to stop, and not ALSO on isInterrupted.
while (!mExited && !Thread.getCurrentThread().isInterrupted()) {
Or it could exit when interrupted :
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return; // supposing there is no cleanup or other stuff to be done
}
Setting the isInterrupted flag back to true is also important if you don't control the Thread. For example, if you are in a runnable which is being executed in a thread pool of some kind, or inside any method anywhere you don't own and control the thread (a simple case : a servlet), you don't know if the interruption is for "you" (in the servlet case, the client closed the connection and the container is trying to stop you to free the thread for other requests) or if it's targeted at the thread (or system) as a whole (the container is shutting down, stopping everything).
In that situation (which is 99% of the code), if you cannot rethrow the InterruptedException (which is, unfortunately, checked), the only way to propagate up the stack to the thread pool that the thread has been interrupted, is setting the flag back to true before returning.
That way, it will propagate up the stack, eventually generating more InterruptedException's, up to the thread owner (be it the jvm itself, of an Executor, or any other thread pool) that can react properly (reuse the thread, let it die, System.exit(1) ...)
Most of this is covered in chapter 7 of Java Concurrency in Practice, a very good book that I recommend to anyone interested in computer programming in general, not just Java, cause the problems and the solutions are similar in many other environments, and explanations are very well written.
Why Sun decided to make InterruptedException checked, when most documentation suggests to rethrow it mercilessly, and why they decided to clear the interrupted flag when throwing that exception, when the proper thing to do is setting it to true again most of the time, remains open for debate.
However, if .wait releases the lock BEFORE checking for the interrupt flag, it open a small door from another thread to modify the mExited boolean. Unfortunately the wait() method is native, so source of that specific JVM should be inspected. This does not change the fact that the code you posted is coded poorly.

Categories

Resources