33

Hypothetical scenario:
I have a daemon thread responsible for some I/O, the main thread finishes and returns, and the JVM decides to terminate my daemon thread.

How does it do so? Interrupt? Finalize? How can I code my daemon thread so that it reacts gracefully when terminated?

rgettman
  • 176,041
  • 30
  • 275
  • 357
Aaron J Lang
  • 2,048
  • 3
  • 20
  • 27
  • 1
    Did you look at the sourcecode? – Stephen C Dec 29 '11 at 02:35
  • 2
    @StephenC That hadn't occurred to me, and would definitely yield a definitive answer (although not _necessarily_ a useful one). I personally, however, am not brave enough to attempt that and don't really expect anyone else to. – Aaron J Lang Dec 29 '11 at 02:40
  • All right, let me be more explicit. The best way to answer a question like this is to look at the source code, or at least the Java code. Generally speaking it is easy to read and well commented. (And I fail to understand how a definitive answer to a question is less useful than a non-definitive one ... especially if *you* were the person reading the code!) – Stephen C Dec 29 '11 at 08:13
  • 14
    Telling the OP to look at the source code is no answer. That shows a particular implementation, not the API requirements. Documentation has its place. – Raedwald Oct 18 '13 at 07:24

4 Answers4

13

I just wrote the following code as a test:

public class DaemonThreadPlay {
    public static void main(String [] args) {
        Thread daemonThread = new Thread() {
            public void run() {
                while (true) {
                    try {
                        System.out.println("Try block executed");
                        Thread.sleep(1000l);
                    } catch (Throwable t) {
                        t.printStackTrace();
                    }
                }
            }

            @Override
            public void finalize() {
                System.out.println("Finalize method called");
            }
        };
        daemonThread.setDaemon(true);
        daemonThread.start();

        try {
            Thread.sleep(2500l);
        } catch (Throwable t) {
            //NO-OP
        }
    }
}    

I put breakpoints in the catch block of the daemon thread and in the finalize method. Neither breakpoint was reached even though the try block was executed. Obviously this code has synchronization/timing issues, but I think we can safely conclude that daemon threads are not interrupted on shutdown nor are their finalize() methods necessarily invoked.

You can always add a shutdown hook to the JVM Runtime:

Thread shutdownHook = ... // construct thread that somehow
                          // knows about all the daemon threads
Runtime.getRuntime().addShutdownHook(shutdownHook);

Your shutdown hook can obviously do whatever tasks are required for a "graceful" shutdown.

Arsen Davtyan
  • 1,891
  • 8
  • 23
  • 40
skiller3
  • 386
  • 2
  • 4
  • 1
    I'm liking the shutdown hook. – Bob Kuhar Dec 29 '11 at 02:16
  • Found [this](http://stackoverflow.com/questions/1323408/get-a-list-of-all-threads-currently-running-in-java/3018672#3018672) when looking for ways to get active threads. Would have to iterate over array to check for at least one user thread.
    I think a shutdown hook is the best solution, never knew about this functionality before. I think I'll keep a reference to my shutdown hook in my Main class, and keep a collection of my daemon threads in the shutdown hook. Then I can just interrupt them all. I'll try to post my code once I implement it.
    – Aaron J Lang Dec 29 '11 at 02:19
  • 2
    If you call `System.gc()` explicitly and the JVM option `-XX:+DisableExplicitGC` is not set, then the daemon thread will exit. This means Garbage Collector is responsible for shutting down the daemon threads after all user threads finish. – George Sep 26 '12 at 07:41
  • Another thing that you can do is that introducing a finally block, this is guaranteed to be invoked no matter what happens inside the try-catch block! In that way you can close any resources that the Daemon thread opened and implement any graceful termination in there! – HackerMonkey Sep 21 '16 at 15:44
  • @skiller3 Be careful not to jump to conclusions. When the JVM is stopped during visual debugging, chances are, that breakpoints won't be hit at all, because the JVM already disconnected from the debugger (I witnessed this behavior with IntelliJ IDEA). – Nico Mar 03 '21 at 18:17
7

I think you misunderstand what a daemon thread is.

See what is a daemon thread in java

In summary, it basically means that a daemon thread shouldn't be doing any I/O or holding any resources. If you are contravening this basic rule then your thread doesn't qualify being a daemon thread.

Adding a shutdown hook is the standard way of ensuring your code gets invoked prior to JVM termination, but even this isn't 100% guaranteed - your JVM could crash for example, leaving the OS to tidy up resources in a way which protects the OS, but quite likely leaves your application in an inconsistent/erroneous state.

System checkpointing and recovery mechanisms go back to the early days of software (operating systems and batch operations for example), and unfortunately, this wheel keeps getting re-invented as there's no "silver bullet" approach (API) which tackles this problem in a generic enough way.

Community
  • 1
  • 1
KRK Owner
  • 762
  • 7
  • 16
  • What's the basis for the claim that Daemon threads shouldn't be doing IO or holding resources? – ykaganovich Dec 20 '13 at 22:49
  • Follow the link provided and you will get some insights. – KRK Owner Jan 14 '14 at 21:16
  • 2
    sorry, I disagree. As long as it's understood that a Daemon thread can be killed mid-processing, there's no danger, unless you know something about java resource leaks that I don't. – ykaganovich Jan 14 '14 at 21:31
  • 2
    It's insane to terminate the JVM if the daemon thread holds hundreds of resources, even worse, the shutdown occurs when it's in the middle of a sequence of critical write operations. You're effectively risking a point of consistency in your app. You are also disagreeing with Brian Goetz who wrote "Java Concurrency in Practice" ... it's fine to disagree, however I think there are a very small number of cases where you could be right. – KRK Owner Jan 16 '14 at 15:21
4

AFAIK,Daemon threads not really for main stream I/O work. If all threads are completed, JVM may close all daemon threads abruptly. The possible work around for your requirement will be create a ExecutorService like below:

ExecutorService execPool = Executors.newSingleThreadExecutor(new ThreadFactory() {

    @Override    
    public Thread newThread(Runnable runnable) {       
         Thread thread = Executors.defaultThreadFactory().newThread(runnable);
         thread.setDaemon(true);
         return thread;    
    } 
}); 

invoke executorservice shutdown method from Shutdown hook.

Runtime.getRuntime().addShutdownHook(....)
maqjav
  • 2,310
  • 3
  • 23
  • 35
kosa
  • 65,990
  • 13
  • 130
  • 167
  • your newThread method does indeed create a new thread factory every time. a call to `Executors.defaultThreadFactory()` just returns a `new DefaultThreadFactory()` – benez Mar 25 '16 at 19:30
1

use interrupt and join:

class Daemon extends Thread {
    public void run() {
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println(e);
                break;
            }
        }
        System.out.println("exit run()");
    }
}   
public class So8663107 {
    public static void main(String[] arguments) throws InterruptedException {
        System.out.println(Thread.activeCount());
        Daemon daemon = new Daemon();
        daemon.setDaemon(true);
        daemon.start();
        Thread.sleep(2500);
        System.out.println(Thread.activeCount());
        daemon.interrupt();
        daemon.join();
        System.out.println(Thread.activeCount());
    }
}
Andrii Abramov
  • 10,019
  • 9
  • 74
  • 96
Ray Tayek
  • 9,841
  • 8
  • 50
  • 90
  • 3
    I don't think you understood the question. I don't want to interrupt my daemon thread(s). I want to know how the JVM terminates them, and how to deal with it. – Aaron J Lang Dec 29 '11 at 02:23
  • sorry, i was attempting to answer: "How can I code my daemon thread so that it terminates gracefully?" – Ray Tayek Dec 29 '11 at 23:40