2017-01-03 15 views
5

Posiadam działający obiekt A, który wymienia sygnały bicia serca z serwerem podczas tworzenia instancji. Przesyłam n takich obiektów do usługi executora z ustalonym rozmiarem puli wątków n. Gdy metoda run napotka wyjątek, zwróci. Dla danego przypadku wszystkie moje wątki napotykają wyjątek i powrót, ale utworzony obiekt pozostaje żywy i nadal wymienia sygnały bicia serca. Jak oznaczyć takie obiekty do zbierania śmieci, aby zatrzymać wymianę sygnałów bicia serca?Kiedy w ExecutorService można pobierać działające śmieci obiektów?

class A implements Runnable { 
    public void run(){ 
      try{ 
      \\throws error 
      } catch(Exception e){ 
      \\returns 
      } 
     } 

    public static void main(){ 
      ExecutorService executor = Executors.newFixedThreadPool(n) 
      for(i = 1 to n){ 
       A a = new A() 
       executor.submit(a) 
      } 
     } 
} 

Czy powinienem założyć połączenie oczekujące na końcu mojej magistrali i złożyć zwrot?

Edycja:
Umieszczenie zapytania w inny sposób, w jedną stronę, aby zakończyć executorservice po wszystkich nici powrotu byłoby nazwać zamknięcie() po pętli i wywołać awaitTermination z Integer.MAX długich sekund, co jest mniej 70 lat (co jest ograniczeniem czasowym, na które niechętnie się nakładam). Czy jest jakaś inna alternatywa?

+0

myślę, że należy pisać kod, który został użyty do wymiany sygnałów heart beat. – AmjadD

+0

Wywołanie rytmu serca nie jest jawne, odbywa się przez bibliotekę. – ankshah

+2

Jeśli nadal widzisz bicie serca po zakończeniu metody 'run()', to nadal masz 'Runnable', który nie został zakończony, * nawet jeśli uważasz, że wszyscy mają *. Sugeruję logowanie ID wątku jako pierwszego kroku 'run()', a także tuż przed każdym poleceniem return. Użyj 'Thread.currentThread(). GetId()'. – kdgregory

Odpowiedz

1

jednym ze sposobów rozwiązania executorservice po wszystkich nici powrotu byłoby nazwać zamknięcie() po pętli i wywołać awaitTermination z Integer.MAX długich sekund, co jest w przybliżeniu 70 lat

jak doc mówi metoda awaitTermination zablokuje util:

  1. wszystkie zadania zostały zakończone wykonanie po żądaniu wyłączenia
  2. lub przekroczenie limitu czasu,
  3. lub bieżący wątek zostaje przerwana, cokolwiek się stanie, pierwszy


Więc będzie koniec gry, gdy tylko jeden z trzech razie obrócić do góry, zamiast musiał czekać 70 lat.

+0

Mój problem polegał na tym, że nie trzeba czekać 70 lat, ale mój kod przestał działać po upływie 70 lat :) – ankshah

+0

@ ankshah twój kod zostanie zamknięty po min (wszystkie zadania zakończone, 70-letni limit czasu, bieżący wątek zostanie przerwany) –

+1

Tęskniłeś za tym ponownie. Chcę pozwolić, aby moje zadanie przebiegło _beyond_70 lat. Jest to konsument wiadomości, tj. Chcę pozwolić mu na konsumpcję dłużej niż 70 lat. Bardzo optymistycznie, wiem. – ankshah

0
Wywołanie zamknięcia() na puli oznacza, że ​​pula nie będzie akceptować żadnego nowego zadania do wykonania, ale bieżące będą działały bez przerwy.

Wywoływanie awaitTermination (timeout) zatrzymuje wątek wywołujący, dopóki pula nie zostanie ukończona, ale jeśli zostanie osiągnięty limit czasu, bieżący wątek zgłasza wykonanie, ale nie wpłynie to na zadania w puli.

Jeśli Twój runnable zgłasza wyjątek uncought, gdy jest uruchamiany przez pulę wątków, to ten runnable nie jest już w stanie uruchomienia - pula wątków zwykle nie odwołuje się do takiego obiektu.

Jeśli używasz FixedThreadPool, to ta pula utworzy tyle wątków, ile chcesz, i nie zatrzyma żadnego z nich, dopóki nie wywołasz shutdown() w tej puli.

Jeśli nie masz odniesienia do działającego obiektu, który rzucił wyjątek, zachowuje się jak zwykły obiekt bez odwołań do Garbage Collected.

jeśli wywołasz shutdown(), a następnie oczekujesz() na pulę wątków, a twój program i tak nie przestanie, to znaczy, że nie wszystkie instancje twojego runnable'a rzuciły wyjątek, a niektóre wciąż działają, blokując pula od całkowitego wyłączenia.

w Javie nie można zabić lub zatrzymać uruchomiony wątek właśnie takiego (można zabić tylko całą JVM używając np. System.exit(0), ale nie tylko wybrane nici), jeśli potrzebujesz takiej funkcjonalności musisz zaprogramować ciało działający w sposób, który pozwala ci jakoś komunikować się z nim, np. za pomocą zmiennej "volatile boolean" i że zareaguje na zmianę wartości tej zmiennej - oznacza to, że musisz dodać "jeśli sprawdza" dla wartości tej zmiennej w treści metody run(), która zwróci kiedy powinien.

0

Same zadania kwalifikują się do zbierania śmieci, gdy tylko zostaną zakończone. Jeśli i kiedy zostaną zebrane, zależy od odśmiecacza.

Przykładowy kod:

public class Main implements Runnable { 
    @Override 
    protected void finalize() throws Throwable { 
     super.finalize(); 
     System.out.println("finalize"); 
    } 

    @Override 
    public void run() { 
     try { 
      throw new Exception("Error"); 
     } catch (Exception e) { 
      //returns 
     } 
    } 

    public static void main(String args[]) { 
     int n = 8; 
     ExecutorService executor = Executors.newFixedThreadPool(n); 
     for (int i = 0 ; i < n; ++i) { 
      Main a = new Main(); 
      executor.submit(a); 
     } 
     System.gc(); 
     System.out.println("end"); 
    } 
} 
Powiązane problemy