2009-03-06 10 views
8

Chcę napisać demona wiersza poleceń, który działa wiecznie. Rozumiem, że jeśli chcę, aby JVM mogła bezpiecznie zamknąć się w Linuksie, trzeba zawinąć bootstrap za pomocą jakiegoś kodu C. Myślę, że na razie będę w porządku z hakiem wyłączającym.Czy Future.get() jest zamiennikiem Thread.join()?

do mojego pytania:

  1. Mój główny ([] String) blok będzie wystrzelić oddzielny superdemonem.
  2. Superdaemon będzie odpytywać i zapętlać na zawsze.

Więc normalnie bym zrobił:

class Superdaemon extends Thread { ... } 

class Bootstrap 
{ 
    public static void main(String[] args) 
    { 
     Thread t = new Superdaemon(); 
     t.start(); 

     t.join(); 
    } 
} 

Teraz pomyślałem, że gdybym zaczął superdemonem pośrednictwem Wykonawcy, mogę zrobić

Future<?> f = exec.submit(new Superdaemon()); 

f.get(); 

Czy Future.get() realizowane z Thread.join() ? Jeśli nie, czy zachowuje się równoważnie?

Pozdrawiam,

Ashitaka

Odpowiedz

12

Tak, sposób, w jaki je napisałeś, jest równoważny.

Jednak nie trzeba czekać na zakończenie wątku Superdaemona. Kiedy główny wątek kończy wykonywanie main(), wątek ten jest zamykany, ale JVM nie. JVM będzie działać, dopóki ostatni wątek nie będący demonem zakończy swoją metodę uruchamiania.

Na przykład

public class KeepRunning { 
    public static void main(String[] args) { 
    Superdaemon d = new Superdaemon(); 
    d.start(); 
    System.out.println(Thread.currentThread().getName() + ": leaving main()"); 
    } 
} 

class Superdaemon extends Thread { 
    public void run() { 
    System.out.println(Thread.currentThread().getName() + ": starting"); 
    try { Thread.sleep(2000); } catch(InterruptedException e) {} 
    System.out.println(Thread.currentThread().getName() + ": completing"); 
    } 
} 

Zobaczysz wyjścia:

main: leaving main() 
Thread-0: starting 
Thread-0: completing 

Innymi słowy, główny wątek zakończy, potem wątek wtórny uzupełnia i wychodzi JVM.

0

Sort'a. Future.get() służy do wyłączania wątku i kalkulowania go, a następnie zwracania go do wątku wywołującego w bezpieczny sposób. To zadziała, jeśli get nigdy nie zostanie zwrócone. Ale będę trzymać się z wezwaniem join, ponieważ jest to prostsze i nie ma narzuć Executer (nie byłoby wszystkiego tak dużo).

Edit

Wygląda ExecutorService.submit(Runnable) ma zrobić exectly co próbujesz. To po prostu zwraca null po zakończeniu Runnable. Ciekawy.

+0

Problem polega na tym, że książki takie jak JCIP opowiadają się za użyciem Executorów do uruchamiania wątków. Więc staram się nie używać Thread.start(). Nie jestem pewien, czy koniecznie wybrałbym konkretny sposób robienia rzeczy w oparciu o prostotę. Musi być bardziej przekonujący powód, nie? – ashitaka

1

Future.get() otrzyma przyszłą odpowiedź z połączenia asynchronicznego. Będzie to również blokować, jeśli połączenie nie zostało jeszcze zakończone. Jest bardzo podobny do łączenia nici.

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Future.html

+0

Podobny, choć wydaje się, że będzie "również" obalił wszystkie niezatłoczone wyjątki: http://abd-tech.blogspot.com/2011/09/throw-exception-from-java-thread-and.html – rogerdpack

6

Problem jest, że książki takie jak JCIP opowiada, że ​​używamy Executory do załączanie wątkach. Więc staram się nie używać Thread.start(). Nie jestem pewien, czy koniecznie wybrałbym konkretny sposób robienia rzeczy w oparciu o prostotę. Musi być bardziej przekonujący powód, nie?

Przekonywanie powodów, by używać java.util.concurrent jest to, że programowanie wielowątkowe jest bardzo trudne. Java oferuje narzędzia do tego celu (Nici, zmienne słowa kluczowei), ale nie oznacza to, że możesz bezpiecznie używać ich bezpośrednio, nie strzelając sobie w stopę: zbyt duża synchronizacja, co powoduje niepotrzebne wąskie gardła i zakleszczenia lub zbyt słabo, co powoduje nieregularne zachowanie ze względu na warunki wyścigu).

Z java.util.Współbieżny dostajesz zestaw narzędzi (napisany przez ekspertów) dla najczęściej używanych wzorców użycia, które możesz po prostu użyć bez obawy, że masz niski poziom rzeczy w porządku.

W danym przypadku, chociaż ja nie bardzo rozumiem, dlaczego potrzebny jest osobny wątek w ogóle, równie dobrze można użyć główny:

public static void main(String[] args) 
{ 
    Runnable t = new Superdaemon(); 
    t.run(); 
} 

Komornicy są przeznaczone do zadań, które chcesz działa w tle (gdy masz wiele zadań równoległych lub gdy twój bieżący wątek może nadal robić coś innego).

Powiązane problemy