2012-06-22 16 views
6

Spingo i miei Futures da un ExecutorService in una mappa hash. Più tardi, potrei chiamare cancel su Futures dall'interno della mappa hash. Sebbene il risultato sia vero, in seguito ho raggiunto i punti di interruzione all'interno della procedura Callable, come se l'annullamento futuro() non avesse avuto alcun effetto. . Penso che potrebbe essere un caso di due diversi riferimenti qui (anche se gli ID di riferimento sono elencati come lo stesso quando breakpointing), ma chiedevo se alcuni esperti potrebbero carillon Ecco quello che il codice è simile:Attività futura di ExecutorService che non si annulla realmente

ExecutorService taskExecutor = Executors.newCachedThreadPool(); 
Map <String, Future<Object>> results = new HashMap <String, Future<Object>>();  

Future<Object> future = taskExecutor.submit(new MyProcessor(uid)); 
results.put(uid, future); 

Acconsento il trattamento per continuare (si tratta di un ciclo che invia compiti sono passati a), e più tardi mi può tentare di cancellare da una fonte esterna chiamando questo metodo:

public static synchronized boolean cancelThread(String uid) { 
    Future<Object> future = results.get(uid); 
    boolean success = false; 
    if (future != null) { 
     success = (future.isDone() ? true : future.cancel(true)); 
     if (success) 
      results.remove(uid); 
    } 
    return success;  
} 

Ma ho ancora incontrare un "non -cancelled "percorso all'interno di MyProcessor.call() dopo che è stato chiamato future.cancel(), cioè non viene effettivamente cancellato.

Dove sto andando male con questo? C'è di meglio è stato per fare questo?

risposta

13

In seguito, ho raggiunto i punti di interruzione all'interno della procedura Callable, come se l'annullamento futuro() non avesse avuto alcun effetto.

Future.cancel(true) rimuove un lavoro che è in coda e non ancora funzionante, ma se il lavoro è già in esecuzione che fa l'equivalente di Thread.interrupt(). Ciò imposta il bit di interrupt sul thread e causa qualsiasi sleep(), wait() e alcuni altri metodi per generare InterruptedException.

È importante rendersi conto che fa non interrompere il thread. È necessario verificare attivamente il flag di interruzione nel loop di thread o gestire correttamente InterruptedException.

Vedi il mio SO risposta qui per maggiori dettagli:

how to suspend thread using thread's id?

+0

Relativo anche a: http://stackoverflow.com/questions/6698977/thread-interrupt-will-it-cancel-oncoming-wait-call – Gray

+0

Vedo che ha senso - Non sono in attesa () stato a questo punto in Callable, quindi non sta lanciando InterruptedException per me. Sfortunatamente, quello che sto cercando di cancellare è una singola chiamata a un database una volta che è già stata avviata, quindi nella migliore delle ipotesi posso mettere un test per se il thread è interrotto in seguito. –

+0

Per chiarire, questa è l'affermazione in cui mi trovo probabilmente quando viene richiesto l'annullamento, una PreparedStatement nel database: 'stmt.execute();' Quindi suppongo di dover lasciare che il database finisca il corso e controllare l'interruzione in seguito. –

0

FutureTask :: boolean cancel(boolean mayInterruptIfRunning) si esibiranno interrupt sul thread in esecuzione corrente.

FutureTask.java 
public boolean cancel(boolean mayInterruptIfRunning) { 
    if (!(state == NEW && 
      UNSAFE.compareAndSwapInt(this, stateOffset, NEW, 
       mayInterruptIfRunning ? INTERRUPTING : CANCELLED))) 
     return false; 
    try { // in case call to interrupt throws exception 
     if (mayInterruptIfRunning) { 
      try { 
       Thread t = runner; 
       if (t != null) 
        t.interrupt();  ////////////HERE///////////// 
      } finally { // final state 
       UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); 
      } 
     } 
    } finally { 
     finishCompletion(); 
    } 
    return true; 
} 

JavaDoc dice il sotto per interrupt

interrupt public void()

Interrompe questo thread. A meno che l'attuale thread si interrompa da solo, il che è sempre consentito, viene invocato il metodo checkAccess di questo thread, che può causare l'emissione di un SecurityException .

Se questa discussione è bloccato in un'invocazione dell'attesa(), attendere (lungo), o attendere (lunghe, int) metodi della classe Object, o del join(), join (lungo), join (long, int), sleep (long) o sleep (long, int), metodi di questa classe, quindi il suo stato di interruzione verrà cancellato e sarà ricevere un InterruptedException.

Se questa discussione è bloccato in un'operazione di I/O su un interrompibile canale, il canale sarà chiusa, lo stato di interruzione del thread sarà impostato, e il filo riceveranno un ClosedByInterruptException.

Se questa discussione è bloccato in un Selettore poi stato di interrupt del thread viene impostato e ritornerà immediatamente dall'operazione selezione , possibilmente con un valore diverso da zero, come se metodo riattivazione del selettore è stata richiamata .

Se nessuna delle condizioni precedenti è valida, verrà impostato lo stato dell'interrupt di questo thread .

L'interruzione di un filo non vivo non deve avere alcun effetto.

Produce: SecurityException - se il thread corrente non può modificare questo discussione

Per concludere; l'annullamento di FutureTask ha un impatto solo se il thread è bloccato (in una chiamata di attesa(), ...) altrimenti è responsabilità dello sviluppatore controllare lo Thread.currentThread().isInterrupted() per uscire; mentre si esegue un'operazione non bloccata.

Problemi correlati