2011-12-29 12 views
27

Scenariusz hipotetyczny:
Mam wątek demona odpowiedzialny za niektóre operacje wejścia/wyjścia, główny wątek kończy się i wraca, a JVM decyduje się zakończyć wątek demona.W jaki sposób JVM kończy wątki demona? lub Jak napisać wątki demona, które kończą się z wdziękiem

Jak to zrobić? Przerwać? Sfinalizować? W jaki sposób mogę zakodować mój wątek demona tak, aby reagował z wdziękiem po zakończeniu?

+1

Czy spojrzałeś na kod źródłowy? –

+2

@StephenC Nie przyszło mi to do głowy i na pewno udzieliłbym definitywnej odpowiedzi (choć niekoniecznie użytecznej). Osobiście jednak nie jestem na tyle odważny, aby podjąć taką próbę i naprawdę nie oczekuję, aby ktokolwiek inny. –

+0

W porządku, pozwól mi być bardziej konkretnym. Najlepszym sposobem, aby odpowiedzieć na takie pytanie, jest sprawdzenie kodu źródłowego lub przynajmniej kodu Java. Ogólnie rzecz biorąc, jest to łatwe do odczytania i dobrze skomentowane.(I nie rozumiem, jak ostateczna odpowiedź na pytanie jest mniej przydatna niż nie definitywna ... szczególnie jeśli * ty * byłeś osobą czytającą kod!) –

Odpowiedz

10

Właśnie napisał następujący kod jako 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 
     } 
    } 
}  

umieścić punkty przerwania w bloku catch wątku demona i sposobu sfinalizowania. Żaden punkt przerwania nie został osiągnięty, mimo że został wykonany blok try. Oczywiście ten kod ma problemy z synchronizacją/synchronizacją, ale myślę, że możemy bezpiecznie wywnioskować, że wątki demona nie są przerywane przy zamykaniu systemu, a ich metody finalize() nie muszą być wywoływane.

Zawsze można dodać hak zamykania do JVM Runtime:

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

Twój hak zamykania można oczywiście zrobić cokolwiek zadania są wymagane dla „wdzięku” wyłączenia.

+1

Podobał mi się hak zamykający. –

+0

Znalezione [this] (http://stackoverflow.com/questions/1323408/get-a-list-of-all-threads-currently-running-in-java/3018672#3018672) podczas wyszukiwania sposobów na uzyskanie aktywnych wątków . Musiałby przejrzeć tablicę, aby sprawdzić co najmniej jeden wątek użytkownika.
Myślę, że hak zamykający to najlepsze rozwiązanie, nigdy wcześniej nie wiedział o tej funkcjonalności. Myślę, że zachowam odniesienie do mojego haka zamykającego w mojej głównej klasie i trzymam kolekcję mych demonów w haku zamykającym. Wtedy mogę po prostu im przerwać. Postaram się opublikować mój kod po jego wdrożeniu. –

+2

Jeśli wywołasz jawnie 'System.gc()', a opcja JVM '-XX: + DisableExplicitGC' nie jest ustawiona, wątek demona zostanie zakończony. Oznacza to, że Garbage Collector jest odpowiedzialny za wyłączenie wątków demona po zakończeniu wszystkich wątków użytkownika. – George

4

AFAIK, wątki Daemon nie są przeznaczone do pracy we/wy głównego strumienia. Jeśli wszystkie wątki zostaną ukończone, JVM może nagle zamknąć wszystkie wątki demona. Ewentualne prace wokół dla Państwa wymagań będą tworzyć ExecutorService jak poniżej:

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

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

invoke metodę wyłączenia z hakiem executorservice Shutdown.

Runtime.getRuntime().addShutdownHook(....) 
+0

Twoja metoda newThread rzeczywiście tworzy nową fabrykę wątków za każdym razem. wywołanie 'Executors.defaultThreadFactory()' zwraca 'new DefaultThreadFactory()' – benez

1

użycie przerwań i dołącz:

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

Nie sądzę, że zrozumiałeś to pytanie. Nie chcę przerywać wątków demona. Chcę wiedzieć, jak JVM je kończy i jak sobie z tym poradzić. –

+0

Przykro mi, próbowałem odpowiedzieć: "Jak mogę zakodować mój wątek demona tak, że kończy się z wdziękiem?" –

+0

Ok, edytowałem pytanie –

5

Chyba nie zrozumiałeś co wątek demon jest.

Zobacz what is a daemon thread in java

Podsumowując, to w zasadzie oznacza, że ​​wątek demon nie należy robić żadnych I/O lub posiadających żadnych zasobów. Jeśli naruszasz tę podstawową zasadę, twój wątek nie kwalifikuje się jako wątek demona.

Dodawanie haka zamykającego to standardowy sposób zapewnienia, że ​​kod zostanie wywołany przed zakończeniem JVM, ale nawet to nie jest gwarantowane w 100% - na przykład JVM może ulec awarii, pozostawiając system operacyjny w taki sposób, aby uporządkować zasoby w sposób który chroni system operacyjny, ale prawdopodobnie pozostawia twoją aplikację w niespójnym/błędnym stanie.

Mechanizmy kontrolowania i odzyskiwania systemu cofają się do początków oprogramowania (na przykład systemów operacyjnych i operacji wsadowych), a niestety, to koło wciąż jest wymyślane od nowa, ponieważ nie ma metody "silver bullet" (API), która rozwiązuje problem ten problem w dość ogólny sposób.

+0

Na jakiej podstawie twierdzono, że wątki Daemona nie powinny wykonywać operacji we/wy lub zatrzymywania zasobów? – ykaganovich

+0

Postępuj zgodnie z podanym linkiem, a uzyskasz informacje. – user924272

+1

Przepraszam, nie zgadzam się. Dopóki jest zrozumiałe, że wątek Daemona może zostać zabity podczas przetwarzania, nie ma niebezpieczeństwa, chyba że wiesz coś o wyciekach zasobów Java, których ja nie mam. – ykaganovich