0

When thread gets terminated (Thread.State.TERMINATED) it is still not interrupted. Why?

I found this, and I found this, but neither answers my question.I have tried this out on OpenJDK 11 and Oracle JDK 16 - no difference, same result.

I have been working with Java for more than 10 years now, and multithreading tasks have always been clear to me; yet, accidentally, I've encountered something strange (to me), which I'm wondering about.

I understand, that private volatile boolean interrupted; is just a flag (field) of class Thread, which I could make use in conjunction with interrupt() in order to code some logic up with the case when isInterrupted() gets true.

However, why does Thread.State.TERMINATED state doesn't also make the same thread interrupted?

public class MainClass {

    public static void main(String[] args) throws Exception {
        Thread alfa = new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                System.out.println(i + ". " + Thread.currentThread().getName() + " state: " + Thread.currentThread().getState().name());
                try {Thread.sleep(1000);} catch (Exception e) {}
            }
        });
        alfa.setName("Alfa thread");
        System.out.println(alfa.getName() + " state before invoking .start() is: " + alfa.getState().name());
        alfa.start();
        int i = 0;
        while (true) {
            ++i;
            System.out.println(i + ". " + alfa.getName() + " state: " + alfa.getState().name());
            System.out.println(i + ". " + alfa.getName() + " is interrupted?: " + alfa.isInterrupted());
            Thread.sleep(1000);
        }
    }
}

demonstrates, this:

Alfa thread state before invoking .start() is: NEW
1. Alfa thread state: RUNNABLE
0. Alfa thread state: RUNNABLE
1. Alfa thread is interrupted?: false
1. Alfa thread state: RUNNABLE
2. Alfa thread state: TIMED_WAITING
2. Alfa thread is interrupted?: false
2. Alfa thread state: RUNNABLE
3. Alfa thread state: TIMED_WAITING
3. Alfa thread is interrupted?: false
4. Alfa thread state: TERMINATED //alfa is terminated!
4. Alfa thread is interrupted?: false //alfa is not interrupted. Seriously?
  • Am I not getting something and this is purposefully done so, as it has some idea behind the scenes? or
  • It is just something, that has been forgotten to be implemented correctly?
dreamcrash
  • 47,137
  • 25
  • 94
  • 117
Giorgi Tsiklauri
  • 9,715
  • 8
  • 45
  • 66
  • 3
    You are never interrupting threads, so obviously they won't have an interrupted state. You seem to be conflating thread termination (== the thread ended) with thread interruption (== signalling to a thread that maybe they should stop what they're currently doing). As such, it is unclear what you're really asking or what problem you're trying to address. – Mark Rotteveel May 02 '21 at 11:46
  • @MarkRotteveel it's bad if it's unclear to you.. which doesn't necessarily mean it is unclear to someone else. Same question to you: how would you revive interrupted thread? I repeat again, what I have said below, that - interruption and killing the thread are DIFFERENT THINGS, and I can understand that semantics (please, read this carefully!), but practically, when the thread is DEAD, what is the point of having its `isInterrupted` state `false`? – Giorgi Tsiklauri May 02 '21 at 11:50
  • 3
    An interrupted thread can 'revive' (although it isn't actually dead so it is not really a matter of reviving, it's only interrupted) itself by clearing its interrupted state and continuing with what it's doing. And let me ask you: What would be the point of having the interrupted flag set to true of a terminated thread that was not interrupted? It wasn't interrupted, it ended 'naturally', so setting interrupted to true makes no sense to me. – Mark Rotteveel May 02 '21 at 11:54
  • ..:) again, and again, and again: I agree, that "interruption" and "termination" are two different things.. I understand that.. from the English language.. from the dictionary.. from my lifetime practical usage and etc. :) YES, one is interrupting, which may be resulting in a temporary state.. whilst another is terminating - which is killing it. If the terminated thread still has a `isInterrupted()` value `false`, then what is the use-case of having benefit over leaving it `false`? can I change the state of interrupted thread from outside that thread? – Giorgi Tsiklauri May 02 '21 at 12:02
  • 1
    `then what is the use-case of leaving it false?` Because it isn't interrupted? And because the docs explain the behaviour - and it is behaving to spec? `A thread interruption ignored because a thread was not alive at the time of the interrupt will be reflected by this method returning false.` – mjwills May 02 '21 at 12:04
  • 2
    Its `isInterrupted()` is false **because it was not interrupted**! There is nothing more to this. What would be the point of setting it to true if it was never interrupted? I really don't understand what you think would be the benefit of setting it true when that doesn't represent the actual reality of not having been interrupted (or having cleared its interrupted state before ending cleanly). I can even guess it might provide some post-mortem information that could be useful, though I can't readily think of an actual use case. – Mark Rotteveel May 02 '21 at 12:06
  • Also, the thread wasn't killed: it ran its course, completed its work and ended ('died of natural causes' for correlation with your use of 'killed'). Termination in this context is not some synonym for "being killed", it means "coming to an end", and thread state `TERMINATED` is a synonym for "stopped", "ended", "completed". Your confusion seems to stem from thinking thread termination is some extreme and permanent form of interruption, it is not, it is more the transition of having nothing more to do and therefor ceasing to be (though now I might be getting a bit too poetic). – Mark Rotteveel May 02 '21 at 12:16
  • @MarkRotteveel I think you really have a lot of opinionated points which you think are necessarily correct. You propose the context translation.. what does termination mean and how it differs from killing and etc. without bringing any valid arguments to it. Killing and Terminating the thread are quite equivalent and synonymous. – Giorgi Tsiklauri May 02 '21 at 12:23
  • @MarkRotteveel also, initial point of my confusion can be attributed to the Oracle's official OCP 11 prep. course material, where instructor says (citation): "a good example of thread interruption is its termination".. and from there onwards, I, maybe designed a wrong structure in my head.. but the question - in which case it would make sense to have thread interrupted (by the available option to resume it!) and not having thread so, is still valid.. and same to you Mark. With the energy you've used to write these comments, you could have came up with a much better answer.. by just writing it. – Giorgi Tsiklauri May 02 '21 at 12:23
  • @MarkRotteveel would you also say, that termination is not permanent?? By the way.. this course (Oracle's OCP 11 Prep) really contains a lot of mistakes.. I've only spotted (and validated) 9 mistakes in the first three lessons.. and in the `interrupt()` context, there is nothing more than what I wrote above. No deeper or further context is there. – Giorgi Tsiklauri May 02 '21 at 12:24
  • Thread termination is permanent, but it is not some extreme and permanent form of **interruption**. If a thread completed its work and ended it is also terminated; it wasn't killed nor interrupted. And the only form of thread killing Java has had is `Thread.stop()` (deprecated in Java 1.2, and you really should never call it), all other forms of thread termination are cooperative, as in they require the terminating thread to cooperate with ending. – Mark Rotteveel May 02 '21 at 12:29
  • The problem is, I can't answer a question that doesn't make sense to me. However I can give feedback in the comments. Anyway, either the quote you have is horribly wrong (and I would treat the remainder of that course material with a heap of salt), or it is missing a lot of context. – Mark Rotteveel May 02 '21 at 12:30
  • I'm already worried whether shall I suggest this course to my students or not.. I was just examining its materials.. that's how I found this.. and as I said - 9 other validated mistakes (in just first three videos). – Giorgi Tsiklauri May 02 '21 at 12:31
  • @GiorgiTsiklauri i've edited my answer to try to clarify everything. Hope this will solve your doubts :) – Frank Soll May 02 '21 at 14:35

1 Answers1

8

A Thread.State of TERMINATED means that the specified Thread has completed execution. A terminated Thread is not interrupted, you're probably mixing the two things, which are different.

The isInterrupted() method returns true only if the thread has been interrupted by another thread via the interrupt() method.

Take a look here: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

Thread termination does not imply thread interruption, because they are two different and independent things.

Edit:

I've seen in the comments that you have a bit of confusion with the interruption, so I wanted to clarify it.

So, basically an interrupt is an indication to a thread, that it should stop what's currently doing, and do something else. So, an interrupted thread is not stopped or suspended (since you used the word resume), but it is a thread that should stop what's doing. For example let's say that a thread named myThread is currently busy on a really long operation, like this:

public void reallyLongOperation() throws InterruptedException {
  // the thread will stay in the loop for a long time
  while(!taskFinished){
    //stuff repeated for many cycles
    if(Thread.interrupted()){
      throw new InterruptedException("The really long operation has been interrupted");
    }
  }
}

Now, let's say the user wants to cancel this really long operation by pressing a button on the GUI. The AWT-EventQueue thread calls myThread.interrupt(). Now myThread is still doing stuff in the cycle, but when the thread reaches the condition, Thread.interrupted() clears the flag and returns true, since it has been interrupted. InterruptedException is thrown, and we have to handle it like every other checked exception.

Now, what's the difference between myThread.isInterrupted() and Thread.interrupted()?

  • myThread.isInterrupted() only returns true if the interrupted flag is true. Though, it does not reset the flag.
  • Thread.interrupted() is a static method, and like the former returns true if the interrupted flag is true, but it also clears it.

When a Thread dies, and it has never been interrupted, or if the flag has been cleared before, both the methods above will return false.

Thread interruption has nothing to do with thread's status, nor with suspension.

Frank Soll
  • 420
  • 1
  • 4
  • 15
  • 1. So, you consider `reallyLongOperation` being called from within `@Override public void run() {..}`, right?; 2. I'm not sure what is `AWT-EventQueue`, but I guess, it's something from old `Abstract Window Toolkit API` and that's the thread which creates the button you've mentioned; 3. `myThread` will continue doing the stuff, because you never verify anything like `isInterrupted()` at the entrance of the thread.. however, if you have `while(Thread.interrupted()) {...}` only in the `void run()` of the `myThread` thread, itself, then the moment you invoke `interrupt()` thread will exit. – Giorgi Tsiklauri May 02 '21 at 14:51
  • @GiorgiTsiklauri 1. Exactly. 2. Yes, It's the AWT thread that handles every event, like the button one. Obviously any thread can do the interrupt operation. 3. Yes. – Frank Soll May 02 '21 at 15:00
  • Fine.. so, I can't check `this.isInterrupted()` inside the current thread's `public void run()`.. and it I'll have `if (Thread,interrupted()){..}` in the `public void run()` method, then changing the `interrupted` flag will ONLY affect that `if`.. and will no NO effect on the thread's performance at all.. the point is, that then I can do whatever I wish in the body of `if`, when `Thread.interrupted()` evaluates to true. If I've formulated all clearly.. Besides, it's a bit weird, why we don't have `this.isInterrupted()` if I want to check `interrupted` flag within the thread itself. – Giorgi Tsiklauri May 02 '21 at 15:04
  • @GiorgiTsiklauri you can obviously do what you want, and use the method you want. The only difference is that `Thread.interrupted()` resets the flag, while the other not. You can use `this.isInterrupted()` but keep in mind that the `interrupted` flag will still be true, so the thread will keep its interrupted state, and if you call methods like `Thread.sleep` or `Object.wait()`, an `InterruptedException` will be thrown. Also, both methods do not have effect on the thread's performance. – Frank Soll May 02 '21 at 15:13
  • 1
    Got it. Thanks.. just as a side-note: `this.isInterrupted()` is not available when using lambda.. and is available when extending Thread.. – Giorgi Tsiklauri May 02 '21 at 15:14
  • `Thread alfa = new Thread(() -> { if (this.isInterrupted()) /*this doesn't work*/ .});` and if extending `Thread` and then overriding `run()`, then `this.isInterrupted()` is available.. probably that's about `this` in lambda.. and not about threads, per se. – Giorgi Tsiklauri May 02 '21 at 15:20
  • @GiorgiTsiklauri it is because of the nature of lambdas. You can use `Thread.currentThread().isInterrupted()` instead, which is less clean but it does its job well. – Frank Soll May 02 '21 at 15:23
  • Yeah.. `this` refers to the closure.. enclosing class.. not the scope of lambda. – Giorgi Tsiklauri May 02 '21 at 15:23