2012-06-22 10 views
6

Empujo mis futuros desde un ExecutorService a un mapa hash. Más tarde, puedo llamar cancelar en futuros desde dentro del mapa hash. Aunque el resultado es cierto, más tarde toco puntos de interrupción dentro del procedimiento de llamada, como si la cancelación futura() no tuviera ningún efecto. . Creo que podría ser un caso de dos referencias diferentes aquí (a pesar de que los ID de referencia se enumeran como el mismo cuando breakpointing), pero preguntaba si algunos expertos podrían meter su cuchara Esto es lo que se ve el código como:Tarea futura de ExecutorService que no cancela 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); 

que permiten que continúe el procesamiento (que es un bucle que presenta las tareas a medida que se pasan en), y más tarde puede intentar cancelar de una fuente externa llamando a este método:

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

Pero todavía encontrarse con un "no -cancelled "ruta dentro de MyProcessor.call() después de llamar a future.cancel(), es decir, no se está cancelando en realidad.

¿Dónde me estoy equivocando con esto? ¿Hay algo mejor para hacer esto?

Respuesta

13

Más tarde llegué a los puntos de interrupción en el procedimiento de llamada, como si la cancelación futura() no tuviera ningún efecto.

Future.cancel(true) elimina un trabajo que está en la cola y sin embargo no se está ejecutando, pero si el trabajo ya se está ejecutando lo hace el equivalente a Thread.interrupt(). Esto establece el bit de interrupción en la secuencia y provoca sleep(), wait() y algunos otros métodos para lanzar InterruptedException.

Es importante tener en cuenta que no no detener el hilo. Debe verificar activamente el indicador de interrupción en su bucle de subprocesos o manejar correctamente InterruptedException.

Ver mi así respuesta aquí para más detalles:

how to suspend thread using thread's id?

+0

También relacionado con: http://stackoverflow.com/questions/6698977/thread-interrupt-will-it-cancel-oncoming-wait-call – Gray

+0

Veo, eso tiene sentido - No estoy esperando () estado en este punto en la llamada invocable, por lo que no está arrojando la excepción InterruptedException para mí. Desafortunadamente, lo que intento cancelar es una sola invocación de estado a una base de datos una vez que ya ha comenzado, por lo que en el mejor de los casos puedo probar si el hilo se interrumpe después. –

+0

Para aclarar, esta es la afirmación en la que probablemente me encuentre cuando solicite la cancelación, un PreparedStatement en la base de datos: 'stmt.execute();' Así que supongo que tengo que dejar que la base de datos termine el curso, y luego verifique la interrupción. –

0

FutureTask :: boolean cancel(boolean mayInterruptIfRunning)interrupt realizará en hilo de ejecución actual.

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 el siguiente para interrupt

interrupción public void()

interrumpe este hilo. A menos que el subproceso actual se interrumpa, lo que siempre está permitido, se invoca el método checkAccess de este subproceso, que puede provocar la apertura de SecurityException.

Si este hilo está bloqueado en una invocación de la espera(), espere (largo), o espere (Long, int) los métodos de la clase Object, o de la unión(), unen (largo), join (long, int), sleep (long) o sleep (long, int), métodos de esta clase, luego se borrará su estado de interrupción y recibirá una interruptedException.

Si este hilo está bloqueado en una operación de E/S sobre un canal interrumpible entonces el canal se cierra, el estado de interrupción de la rosca se establecerá, y el hilo recibirá una ClosedByInterruptException.

Si este hilo se bloquea en un Selector entonces de estado de interrupción del hilo se puede ajustar y volverá inmediatamente de la operación de selección , posiblemente con un valor distinto de cero, tal como si se invoca el método wakeup del selector .

Si no se cumple ninguna de las condiciones anteriores, se establecerá el estado de esta secuencia de hilos.

La interrupción de un hilo que no está vivo no tiene por qué tener ningún efecto.

Lanza: SecurityException - si el thread actual no puede modificar esta hilo

Para concluir; cancelar de FutureTask solo tiene impacto si el hilo está bloqueado (en una invocación de wait(), ...) de lo contrario es responsabilidad del desarrollador marcar Thread.currentThread().isInterrupted() para salir; mientras realiza una operación no bloqueada.

Cuestiones relacionadas