簡體   English   中英

JVM如何終止守護程序線程?或者如何編寫正常終止的守護程序線程

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

假設情景:
我有一個守護程序線程負責一些I / O,主線程完成並返回,JVM決定終止我的守護程序線程。

它是如何做到的? 打斷? 最終確定? 如何對我的守護程序線程進行編碼,以便在終止時能夠優雅地做出反應?

我剛剛編寫了以下代碼作為測試:

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
        }
    }
}    

我將斷點放在守護程序線程的catch塊和finalize方法中。 即使執行了try塊,也沒有達到斷點。 顯然這段代碼有同步/計時問題,但我認為我們可以安全地得出結論,守護程序線程在關閉時不會被中斷,也不一定會調用它們的finalize()方法。

您始終可以向JVM運行時添加關閉掛鈎:

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

您的關閉鈎子顯然可以執行“正常”關閉所需的任何任務。

我想你誤解了一個守護程序線程是什么。

看看java中的守護程序線程是什么

總之,它基本上意味着守護程序線程不應該執行任何I / O或持有任何資源。 如果您違反了這個基本規則,那么您的線程就不能成為守護程序線程。

添加關閉掛鈎是確保在JVM終止之前調用代碼的標准方法,但即使這樣也不是100%保證 - 例如,您的JVM可能會崩潰,讓操作系統以保護操作系統的方式整理資源,但很可能會使您的應用程序處於不一致/錯誤狀態。

系統檢查點和恢復機制可以追溯到軟件的早期階段(例如操作系統和批處理操作),不幸的是,這個輪子不斷重新發明,因為沒有“銀彈”方法(API)可以解決這個問題。通用的方式。

AFAIK,Daemon線程並不真正用於主流I / O工作。 如果所有線程都已完成,JVM可能會突然關閉所有守護程序線程。 可能需要解決的問題是創建一個如下所示的ExecutorService:

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

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

從Shutdown hook調用executorservice shutdown方法。

Runtime.getRuntime().addShutdownHook(....)

使用中斷和連接:

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());
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM