-4
public class ADaemon implements Runnable {
@Override
public void run() {
    try {
        System.out.println("Starting ADaemon");
        TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
        System.out.println("Exiting via InterruptedException");
    } finally {
        System.out.println("This should always run?");
    }
}

public static void main(String... args) {
    Thread t = new Thread(new ADaemon());
    t.setDaemon(true);
    t.start();
}}

result

Starting ADaemon
Exiting via InterruptedException
This should always run?

I tried to the code sample from "Thinking in Java" 4th edition, but it did't get the result as described in the book, the finally block is still being executed, why is that so? BTW I am using oracle jdk 10.0.1.

-------------update----------

It seems there is something run with my maven-runner plugin, I disabled it and it just get the same result as described in the book.

  • 1
    As far as I know, `finally` is supposed to run even if there is an exception. – Jai Jul 23 '18 at 02:28
  • @Jai but in the book, it said as you set the thread to daemon, the finally block may not be executed. – slow_mohammud Jul 23 '18 at 02:32
  • 1
    it's surprising to see that an interrupted exception was thrown here. i can't reproduce this in java 8, it behaves as Bruce says. is this openjdk? – Nathan Hughes Jul 23 '18 at 02:40
  • @NathanHughes it's oracle jdk 10.0.1. – slow_mohammud Jul 23 '18 at 02:45
  • 1
    ***Because*** it's in a `finally` block. That's what they're for. – user207421 Jul 23 '18 at 03:41
  • The book actually said "You should be aware that daemon threads will terminate their run( ) methods without executing finally clauses" to describe the case. The previous one is my paraphrase. – slow_mohammud Jul 23 '18 at 04:04
  • The book actually said "You should be aware that daemon threads will terminate their run( ) methods without executing finally clauses" to describe the case. The previous one is my paraphrase. – slow_mohammud Jul 23 '18 at 04:04

3 Answers3

3

You say that the book says:

"the finally block may not be executed".

(Emphasis added.)

That is not the same as saying:

"the finally block will not be executed".

I think that the book is implying that it is unspecified (and possibly JVM specific) whether daemon thread gets an interrupt (or something) when the application exits.

Certainly, if the daemon thread caught and ignored the "interrupted" exception as follows, then I would expect that the finally to never be executed.

public class ADaemon implements Runnable {
    @Override
    public void run() {
        try {
            System.out.println("Starting ADaemon");
            while (true) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    System.out.println("Caught InterruptedException");
                }
            }
        } finally {
            System.out.println("This should always run?");
        }
    }

    public static void main(String... args) {
        Thread t = new Thread(new ADaemon());
        t.setDaemon(true);
        t.start();
    }
}

I would expect similar behavior if the daemon thread was not executing interruptible code.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • The book originally said "You should be aware that daemon threads will terminate their run( ) methods without executing finally clauses" to describe the case, my expression may be a little ambiguous here. But I think the book is trying to say, if the the last non-daemon thread terminates, then it will end all the daemon thread regardless whether their finally block is executed. – slow_mohammud Jul 23 '18 at 03:58
  • 2
    If that's what the book says, it is (technically) incomplete / inaccurate, since the actual behavior *may* depend on what the daemon thread will do in response to an interrupt. (Lesson: books can be wrong. Only trust what the specifications say.) – Stephen C Jul 23 '18 at 04:08
  • Thanks, but have u got any further readings about what the daemon thread will do in reponse to an interrupt? – slow_mohammud Jul 23 '18 at 04:31
  • The `Thread` javadocs would be a good place to start. (The behavior is the same as for a non-daemon thread.) – Stephen C Jul 23 '18 at 04:46
  • Thx. BTW it seems jdk 8 and jdk 10 have different results, so perhaps it has some relations with version change. – slow_mohammud Jul 23 '18 at 04:59
2

This should always run? Yes. Unless the JVM actually halts the finally block is guaranteed to be entered. Something like

System.exit(-1);

in the catch block will prevent that. If that is what you want. It will also stop the JVM! The book is warning you that if all other threads are completed, the daemon thread may never be scheduled before the JVM terminates. You are directly calling start(). Consider using

SwingUtilities.invokeLater(t);

It probably won't run unless you remove t.setDaemon(true);

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • But in the book, it said "Daemon threads will terminate their run() methods without executing finally clauses", the result in the book is actually "Staring Adaemon" without executing the finally. Why is my code execution result different from the one in the book? – slow_mohammud Jul 23 '18 at 02:38
  • The result now is "Starting ADaemon This should always run?", it didn't catch the exception, but finally block is still being executed. – slow_mohammud Jul 23 '18 at 02:44
  • @AlanLian The JVM ends normally when all non-daemon threads have ended. At that time, the JVM will exit, without waiting for daemon threads to end, so the call stack of daemon threads are not unwound and therefore `finally` blocks on the stack are not executed. However that is when the JVM ends, if the code in the daemon thread returns, then of course `finally` blocks are exeucted, because they have to, in order for the call stack to unwind. – Andreas Jul 23 '18 at 02:50
  • @Andreas could explain the detailed difference between the daemon threads return and those don't? I can't get the difference here – slow_mohammud Jul 23 '18 at 03:01
  • @Alan: it's just that it may be a race condition whether the daemon thread finishes normally or the jvm dies. but your 1sec sleep time seems like it gives plenty of time for the main thread to terminate. – Nathan Hughes Jul 23 '18 at 03:07
0

The finally block is a powerful (and dangerous if used incorrectly) tool which will almost always run after the try or catch block completes (despite some small cases which are highlighted above). Look at this example:

try{
  throw new Exception();
}catch(Exception e){
return;
}finally{
System.out.println("Shouldn't run?");
}

If this was in a method, the finally block would still be executed (never do this as it is a bad practise). It is designed to perform any cleanup despite the result of the operation you did such as closing streams (which can now be done automatically through paranthesis in the statement 'try').

Ryan_DS
  • 750
  • 7
  • 28