2016-05-18 9 views
5

Sto utilizzando un CountDownLatch per gestire due thread Java. La mia struttura di classe è la seguente:Java CountDownLatch attende il valore di timeout quando il thread.run() che esegue il conto alla rovescia del latch riceve un'eccezione

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

principali Waits classe fino a quando altri due thread completare il loro lavoro. Non appena completano il lavoro, non attende il suo valore di timeout (20 secondi). Il mio problema è che se uno qualsiasi dei thread viene distrutto o danneggiato, lo CountDownLatch attende il suo valore di timeout. C'è un modo per ignorare quella discussione interrotta e andare avanti senza aspettare 20 secondi?

+0

Cosa intendi con i tuoi Thread che vengono distrutti o corrotti? Lanciare un'eccezione? – Alexander

+4

sposta la chiamata 'latch.countDown()' nel tuo codice thread in un blocco 'finally' in modo che venga eseguita indipendentemente da ciò che accade – zapl

risposta

6

zapl ha assolutamente ragione! Il thread principale è in attesa che il timeout si risolva. Se avete preso una discarica filo durante il tempo che il thread principale è in attesa sul dispositivo di chiusura, si vede qualcosa di simile:

"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) 

Dal Javadoc di await:

Se il valore attuale è maggiore di zero allora il thread corrente diventa disabilitato per fini di programmazione filo e giace dormiente fino una delle tre cose:

  1. il conteggio raggiunge zero a causa alle invocazioni del metodo countDown; oppure
  2. Alcuni altri thread interrompono il thread corrente; oppure
  3. Il tempo di attesa specificato trascorre.

Nel tuo caso, la chiamata await restituisce solo a causa di 3).

Nel CountDownLatch Javadoc, la chiamata al metodo countDown() avrebbe dovuto essere fatto nel blocco 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

È necessario un qualche tipo di notifica quando un thread viene distrutta. Un modo per farlo è catturare lo InterruptedException manualmente all'interno del thread, quindi eseguire il conto alla rovescia dell'errore.

Un altro modo è utilizzare le attività anziché Threads e utilizzare le guaiave ListenableFuture per ottenere le notifiche di errore. This SO Q & A lo spiega bene.