2009-12-16 5 views
13

tengo una tarea larga, algo así como:Java carreras de larga tarea de rosca interrumpir vs cancelar la bandera

public void myCancellableTask() { 
    while (someCondition) { 
     checkIfCancelRequested(); 
     doSomeWork(); 
    } 
} 

La tarea puede ser cancelada (una se solicita y cancelar checkIfCancelRequested() comprueba la bandera cancelar). En general, cuando escribo bucles cancelables como este, uso una bandera para indicar que se ha solicitado una cancelación. Pero, sé que también podría usar Thread.interrupt y verificar si el hilo ha sido interrumpido. No estoy seguro de cuál sería el enfoque preferido y por qué, ¿pensamientos?

gracias,

Jeff

Respuesta

6

interrupción será la explosión de la rosca de una lista de espera de las condiciones especificadas. Tu propia bandera de cancelación no lo hará. Si desea interrumpir las esperas en IO y eventos, use la interrupción. De lo contrario, use el suyo.

0

Creo que es una cuestión de preferencia en la mayoría de los casos. Personalmente iría por la bandera hecha a mano. Le da más control, por ejemplo, de esta manera se asegura de que su hilo no deje a ningún otro objeto en un estado incoherente. Además, si el rendimiento es realmente crítico, tenga en cuenta que el uso de excepciones tiene una carga (incluso si es insignificante en el 99% de los casos).

1

Depende de la implementación doSomeWork(). ¿Es eso computación pura o implica (en algún momento) bloquear llamadas API (como IO)? Por bmargulies's respuesta, muchas API de bloqueo en JDK son interrumpibles y propagarán la excepción interrumpida por la pila.

Por lo tanto, si el trabajo implica el bloqueo de las actividades potencialmente, que need'll interrupciones para tomar en consideración incluso si decide controlar el proceso usando una bandera, y de manera apropiada debe capturar y manejar/propagar las interrupciones.

Más allá de eso, si se basa en una bandera, asegúrese de que su bandera se declare con semántica volatile.

20

Un problema con el uso de interrupción es que si no se controla todo el código que se ejecuta, se corre el riesgo de la interrupción no trabajar "correctamente" a causa de otra persona es la comprensión rota de cómo manejar las interrupciones en su biblioteca. Esa es la API invisiblemente exporta una API en torno a su manejo de interrupt s de la que dependes.

En su ejemplo, supongamos doSomeWork fue en un frasco de 3 ª parte y se ve como:

public void doSomeWork() { 
    try { 
     api.callAndWaitAnswer() ; 
    } 
    catch (InterruptedException e) { throw new AssertionError(); } 
} 

Ahora tiene que manejar una AssertionError (o cualquier otra cosa que la biblioteca está utilizando podría lanzar). ¡He visto a desarrolladores experimentados arrojar todo tipo de tonterías al recibir interrupciones! Por otro lado, tal vez el método era la siguiente:

public void doSomeWork() { 
    while (true) { 
     try { 
      return api.callAndWaitAnswer() ; 
     } 
     catch (InterruptedException e) { /* retry! */ } 
    } 
} 

Esta "manipulación inadecuada" de interrupción hace que su programa de bucle indefinidamente. Nuevamente, no descarte esto como ridículo; hay muchos mecanismos de manejo de interrupciones rotos por ahí.

Al menos usar su propio marcador será completamente invisible para las bibliotecas de terceros.

+1

Buenas cosas aquí. Es muy común ver cómo se traga la interrupción o simplemente iniciar sesión y continuar sin restablecer el indicador de interrupción. Creo que las personas se sienten frustradas de que sea una excepción controlada que no saben qué hacer, por lo que no hacen nada en absoluto. –

Cuestiones relacionadas