0

Like I am very upset because I do not understand why it does not work.

Here is part of my code:

if (!loadThread.isInterrupted()) {
    try {
        Thread.sleep(500);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

And it gives me error:

W/System.err: java.lang.InterruptedException
W/System.err:     at java.lang.Thread.sleep(Native Method)
    at java.lang.Thread.sleep(Thread.java:442)
    java.lang.Thread.sleep(Thread.java:358)
    at me.igor.comunicator.client.MainActivity$2.run(MainActivity.java:94)

And line 94 Is Thread.sleep(500);. And it is very weird because If it gives my error that Thread is interrupted so why does if(!loadThread.isInterrupted()) { get executed as true?

Gray
  • 115,027
  • 24
  • 293
  • 354
Igorson
  • 51
  • 1
  • 4

3 Answers3

2

You don't appear to understand what interrupt does or how it works.

A short tutorial:

  • Checking the state of other thread's interrupted flag is exceedingly weird. It is likely you wanted Thread.interrupted() instead of loadThread.isInterrupted().
  • When you set the interrupt flag on a thread, nothing happens immediately. We're not waiting around for something that reads the flag to run in that thread, at which point something will happen. There are only 2 interactions with that flag:
    1. is calling Thread.interrupted. If you call that method when your thread's interrupt flag is raised, that will return true, and will lower the flag.
    2. is calling any method that has a specific interaction with that flag. Every method that is specified to throws InterruptedException, such as Thread.sleep, is guaranteed to interact with it: These methods will throw InterruptedException and lower the flag. If the flag is up when you invoke the method, they return immediately by lowering the flag and throwing the exception. Methods that aren't specced to throw InterruptedEx, but which do 'sleep', such as fileInputStream.read(), may or may not interact with it: JVM's choice. Depends on your OS. If they interact with it, they'll lower the flag and throw e.g. IOException. They won't (and can't) throw InterruptedException.

That means a few things for your code:

  1. Of course your isInterrupted() call returns false: It hasn't interrupted YET, that happens during those 500 milliseconds.
  2. In general you don't need the check, at all. The only way to deal with interupts here is to catch that exception. There is simply no other way. That will also take care of all possible occurences, you don't need any check. This is the code you must write, and it covers all relevant cases:
boolean wasInterrupted;
try {
    Thread.sleep(500);
    wasInterrupted = false;
} catch (InterruptedException e) {
    wasInterrupted = true;
}

if (wasInterrupted) {
   // do whatever you intended to do here
}

The reason you don't need to call Thread.interrupted at all is because Thread.sleep will do it for you at no cost (performance or otherwise).

Note that threads never get interrupted by anything, except you specifically writing someThread.interupt(). e.g. the user pressing CTRL+C or going into their task manager or activity monitor or whatnot and ending your process, forcefully or not, does not cause interrupts.

Gray
  • 115,027
  • 24
  • 293
  • 354
rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • 1
    `Thread.interrupted()` is not recommended because it unsets the interrupted flag. `Thread.currentThread().isInterrupted()` is what should be used. The OP's use of `isInterrupted()` is correct. – Gray Aug 03 '21 at 21:58
  • Also, there are many other places which cause a thread to be interrupted without the programmer directly calling `somethread.interrupt()`. `threadPool.shutdownNow()` comes to mind. I understand your point but it could be misinterpretted. – Gray Aug 03 '21 at 22:11
  • @Gray No, you're wrong: Clearing the flag is part of the point. The 'flow' of how to use the interrupt API is designed around clearing that flag once you act on it. – rzwitserloot Aug 04 '21 at 08:51
  • 1
    Yeah no. It's usually not recommended. If you clear the flag then the caller will have no idea that the current thread is interrupted. It's why we reinterrupt the thread when we catch InterruptedException. You typically want to test the interrupt status without clearing and you want to reinterrupt once you catch InterruptedException. – Gray Aug 05 '21 at 03:48
  • _It's usually not recommended_ - Appeal to.. what? It's a logical fallacy in any case. Or, as wikipedians would say it, [citation needed]. But, hey, if appeals are fair game: I'll just say that it is usually recommended. I will even, unlike you, pull in one source for this claim other than myself: The designers of the API itself, which didn't add 'lower that flag' for giggles. They think it the API works better that way. – rzwitserloot Aug 05 '21 at 09:53
  • Yeah sorry. Should have provided refs: https://newbedev.com/why-invoke-thread-currentthread-interrupt-in-a-catch-interruptexception-block https://myshadesofgray.wordpress.com/2014/04/13/and-you-thought-you-knew-java-multithreading/ https://stackoverflow.com/questions/52622554/best-practices-for-handling-interruptedexception https://dzone.com/articles/how-to-handle-the-interruptedexception – Gray Aug 05 '21 at 15:32
  • The designers also added `thread.stop()` which was a tremendously bad idea. Just because the API has a method doesn't mean it is recommended that it be used. There are certainly times where `Thread.interrupted()` is fine but the problem with SO answers is that they can propagate bad patterns even if they make sense in the context of the OP. – Gray Aug 05 '21 at 15:35
1
if(!loadThread.isInterrupted()) {

So the answer depends on whether or not loadThread is the current running thread or another thread running in your application. Since you are in the MainActivity, the current running thread may be the main thread and the loadThread is some background load thread that the current thread is checking the status of.

If loadThread is the current thread then there really isn't any point in testing the interrupt flag. The Thread.sleep() will throw immediately if the flag is set.

W/System.err: java.lang.InterruptedException

This is saying that the current running thread has been interrupted. You can see by the stack trace that the thread was in Thread.sleep(...) when it threw. This may or may not have anything to do with loadThread.

why does if(!loadThread.isInterrupted()) { gets executed as true.

So if the loadThread is the current running thread then it is very possible that it tests its interrupt status and then calls Thread.sleep(). While it is sleeping is when the interrupt gets delivered. I assume this code is in some sort of test loop? The chances of the code getting interrupted outside of the sleep may be actually pretty small. This is classic race condition so the interrupt could be delivered before the isInterrupted() or after during the sleep – the code has to be prepared for either possibility.

Lastly, in most situations it is recommended that you re-interrupt a thread when you catch InterruptedException. The reason is that when InterruptedException is thrown, the interrupt status of the thread is cleared. If you exit the routine, you want the calling code to be able to also test the interrupted flag – you don't want to clear it artificially. There are 3rd party libraries that catch and don't re-interrupt the thread which can cause major problems in threaded applications.

try {
   Thread.sleep(500);
} catch (InterruptedException ie) {
   // immediately re-interrupt the thread so callers can test it too
   Thread.currentThread().interrupt();
   // deal with the interrupt which typically means exiting the the thread
   return;
}
Gray
  • 115,027
  • 24
  • 293
  • 354
0

Your thread is interrupted during waiting (executing Thread.sleep instruction) In that case InterruptedException is thrown.

In your code there is nothing else than Thread.sleep. So it is very little chance that thread running this code will be interrupted after thread.sleep, but before if.isInteruppted.

Your program should not fail - just print stacktrace and go on with exectution (code after try block). In this case it is appropriate to just log.debug when InterruptedException is catch (it is not error).

See https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#sleep(long) for details

Bartosz Bilicki
  • 12,599
  • 13
  • 71
  • 113
  • In most cases it's considered bad form to just continue after catching InterruptedException. Your thread is being interrupted and you typically should have it exit or return. In some situations applications use the interrupt flag to cause a thread to stop sleeping so that it can check something and continue but that logic is less typical. – Gray Aug 03 '21 at 22:41