2016-05-18 4 views
5

Używam CountDownLatch do obsługi dwóch wątków Java. Moja klasa struktura jest następująca:Java CountDownLatch czeka na wartość limitu czasu, gdy wątek.run() odliczający zatrzask otrzymuje wyjątek

MainClass.java
ThreadOne.java
ThreadTwo.java

MainClass:

CountDownLatch latch = new CountDownLatch(2);   
Thread thread = new Thread(new ThreadOne(latch)); 
thread.start(); 

Thread thread1 = new Thread(new ThreadTwo(latch)); 
thread1.start();   

latch.await(20, TimeUnit.SECONDS); 

głównej klasy czeka, aż pozostałe dwa wątki zakończyć swoją pracę. Jak tylko zakończą swoją pracę, nie czekają aż do czasu przekroczenia limitu czasu (20 sekund). Mój problem polega na tym, że jeśli któryś z wątków zostanie zniszczony lub uszkodzony, wtedy CountDownLatch czeka na swoją wartość limitu czasu. Czy istnieje sposób, aby zignorować przerwaną wątek i iść naprzód bez czekania 20 sekund?

+0

Co masz na myśli, gdy wątki zostaną zniszczone lub uszkodzone? Rzucanie wyjątku? – Alexander

+4

Przenieś wywołanie 'latch.countDown()' w swoim kodzie wątku do bloku 'finally', aby zostało wykonane bez względu na to, co się stanie – zapl

Odpowiedz

6

zapl ma absolutną rację! Główny wątek czeka na przekroczenie limitu czasu. Jeśli miała zrzutu wątku w czasie, że główny wątek czeka na zatrzask, można zobaczyć coś takiego:

"main" #1 prio=5 os_prio=31 tid=0x00007fa4be002000 nid=0x1303 waiting on condition [0x000000010b74c000] 
    java.lang.Thread.State: TIMED_WAITING (parking) 
    at sun.misc.Unsafe.park(Native Method) 
    - parking to wait for <0x000000076abcb598> (a java.util.concurrent.CountDownLatch$Sync) 
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215) 
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedNanos(AbstractQueuedSynchronizer.java:1037) 
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1328) 
    at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:277) 

Z Javadoc z await:

Jeśli aktualna liczba jest większa od zera wtedy obecny wątek staje wyłączone dla celów planowania wątek i drzemie aż jedną z trzech rzeczy zdarzyć:

  1. Ilość osiągnie zero należytej do inwokacji metody countDown; lub
  2. Niektóre inne wątki przerywają bieżący wątek; lub
  3. Określony czas oczekiwania upływa.

W twoim przypadku, wywołanie await wraca tylko z powodu 3).

W CountDownLatch Javadoc, wywołanie metody countDown() powinno być zrobione w bloku finally:

public void run() { 
    try { 
     startSignal.await(); 
     doWork(); // may throw exception 
    } catch (InterruptedException ex) { 
     // handle interruption ... 
    } finally { 
     doneSignal.countDown(); // cause await to return asap 
    } 
} 
0

Trzeba jakieś powiadomienia, gdy wątek zostanie zniszczony. Jednym ze sposobów jest złapanie ręcznie w wątku, a następnie odliczanie błędu.

Innym sposobem jest użycie zadań Runnable zamiast Threads i użycie guavas ListenableFuture, aby uzyskać powiadomienia o błędach. This SO Q & A to wyjaśnia.

Powiązane problemy