Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the JVM terminate daemon threads? or How to write daemon threads that terminate gracefully

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?

like image 749
Aaron J Lang Avatar asked Dec 29 '11 01:12

Aaron J Lang


People also ask

How do I terminate a daemon thread?

If you call System. gc() explicitly and the JVM option -XX:+DisableExplicitGC is not set, then the daemon thread will exit.

Why JVM terminates the daemon thread if no user threads are remaining?

Why JVM terminates the daemon thread if there is no user thread? The sole purpose of the daemon thread is that it provides services to user thread for background supporting task. If there is no user thread, why should JVM keep running this thread. That is why JVM terminates the daemon thread if there is no user thread.

What is daemon thread and how it can be set as daemon thread?

A Daemon thread is a background service thread which runs as a low priority thread and performs background operations like garbage collection. JVM exits if only daemon threads are remaining. The setDaemon() method of the Thread class is used to mark/set a particular thread as either a daemon thread or a user thread.

Does daemon thread end before main thread?

The main difference between Daemon thread and user threads is that the JVM does not wait for Daemon thread before exiting while it waits for user threads, it does not exit until unless all the user threads finish their execution.


4 Answers

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.

like image 102
skiller3 Avatar answered Sep 30 '22 12:09

skiller3


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.

like image 30
user924272 Avatar answered Sep 30 '22 12:09

user924272


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(....)
like image 30
kosa Avatar answered Sep 27 '22 12:09

kosa


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());
    }
}
like image 1
Ray Tayek Avatar answered Sep 28 '22 12:09

Ray Tayek