2012-09-01 20 views
6

Estoy desarrollando una aplicación de subprocesos múltiples para hacer conexiones a servidores externos, cada uno en subprocesos separados, y se bloqueará hasta que haya una entrada. Cada uno de estos extiende la clase Thread. En aras de la explicación, llamemos a estos "hilos de conexión".Java: ¿cómo atrapo InterruptedException en un hilo, cuando es interrumpido por otro hilo?

Todos estos hilos de conexión se almacenan en un hashmap simultáneo.

Luego, permito la llamada al método de servicios web RESTful para cancelar cualquiera de los hilos. (Estoy usando Grizzly/Jersey, entonces cada llamada es un hilo en sí mismo).

Recupero el hilo de conexión específico (del hashmap) y llamo al método de interrupción() en él.

Entonces, aquí está la pregunta, dentro del hilo de conexión, ¿cómo atrapo la InterruptedException? (Me gustaría hacer algo cuando el hilo de conexión es detenido por un comando RESTful externo.)

+0

Bien, AFAIK, cuando un hilo arroja InterruptedEx. se propagará hasta el hilo que inició la excepción arrojando hilo. Es en ese hilo padre que puedes atrapar el IE. –

+0

Acabo de hacer un experimento para rodear el código que inicia el hilo de conexión, y el compilador advierte que la InterruptedException no se lanza. – ikevin8me

+0

Además, el subproceso principal que inició esos hilos de conexión no entra en un estado de espera o inactividad, por lo que significa (o al menos eso creo) que deja de existir después de haber iniciado todos los subprocesos secundarios. – ikevin8me

Respuesta

6

Entonces, aquí está la pregunta, dentro del hilo de conexión, ¿cómo atrapo la InterruptedException?

No puede. Dado que si el hilo está bloqueado en una operación de E/S de lectura, no puede ser interrupted. Esto se debe a que el interrupt simplemente establece un indicador para indicar que el hilo ha sido interrumpido. Pero si su hilo ha sido bloqueado para E/S, no verá el indicador.
La forma correcta de hacerlo es cerrar el socket subyacente (al que está bloqueado el hilo), luego atrapar la excepción y propagarla.
Así que desde su conexión de hilos extend Thread haga lo siguiente:

@Override 
public void interrupt(){ 
    try{ 
     socket.close(); 
    } 
    finally{ 
    super.interrupt(); 
    } 
} 

De esta manera es posible interrumpir un hilo bloqueado en la E/S.

Luego, en su método de hacer run:

@Override 
public void run(){ 

    while(!Thread.currentThread().isInterrupted()){  
     //Do your work 

    } 
}  

Así que en su caso no tratan de catch un InterruptedException. No puede interrumpir el hilo bloqueado en E/S. Simplemente verifica si tu hilo ha sido interrumpido y facilita la interrupción cerrando el flujo.

2

el problema es con el bloqueo.

Hoverer, probar este código, tal vez le ayudará a:

try{ 
yourObject.read(); 
}catch(InterruptedException ie){ 
// interrupted by other thread 
} 
catch(Exception ex){ 
// io or some other exception happent 
} 

su método de lectura, debe comprobar si hay buytes disponibles en zócalo para, por ejemplo, si hay que leerlo, othervise ir a SPEEL modo. Cuando está durmiendo de lo que está disponible, el despertador (InterruptedException) en la lectura del zócalo pur (cualquier lectura que tenga) se bloqueará. Algunas API tienen un valor para la espera máxima, por ejemplo, 5 segundos y 60 segundos, si no se lee nada de lo que será el siguiente código ejecutado.

class MyReadingObject 
{ 
    public read() throws InterruptedException{ 
     while(shouldIread){ 
     if(socket.available() > 0){ 
      byte[] buff = new byte[socket.avaialble()] 
      socket.read(buff); 
      return; 
     } 
     else{ 
      Thread.currentThread.sleep(whateverMilliseconds); 
     } 
    } 
    } 
} 

algo por el estilo, pero con manejo de errores y algunos patrones de diseño

+0

Intenté algo así, el problema es que "yourObject.read()" no lanza la InterruptedException. El compilador mostrará un error que indica que ningún lugar en el código arroja esa excepción y se niega a compilar. – ikevin8me

+0

oh, pero puede agregarlo: –

+0

Veo que me bajaron la votación, debería reconsiderar cuánto tiempo voy a perder aquí. gracias a todos. Se servicial, buena suerte! –

-1

utilizar un try-catch, así:

try { 
    //code 
} catch (InterruptedException e) { 
    //interrupted 
} 

creo que debe hacer el truco, también se puede mantener una variable booleana sobre si salir, para que comprueben esa variable, si es verdadera, detenga

+0

¿Dónde pongo esto? En el método run()? - el compilador dirá que el código no lanza la InterruptedException y no compilará. – ikevin8me

2

Cuando llama al Thread.interrupt() en un hilo, lo que sucede es que 'interru ption 'se establece para ese hilo. Algunos métodos comprueban este indicador (por Thread.interrupted() o Thread.isInterrupted()) y lanzan InterruptedException, pero generalmente solo los métodos que pueden bloquearlo hacen eso. Por lo tanto, no hay garantía de que alguna vez se lanzará InterruptedException en una conversación interrumpida. Si no llama a ningún método que arroje InterruptedException, no tiene sentido capturar esa excepción, ya que no se lanzará en absoluto. Sin embargo, siempre puedes verificar si tu hilo fue interrumpido llamando al Thread.isInterrupted().

+0

muy cierto, debe llamar al mycontroller.getReadingThread(). Interrupt(); –

1

Llamar a interrupt() en un hilo no detener, simplemente enciende el indicador de interrupción. Es responsabilidad del código manejar el cambio en el estado de interrupción del hilo en consideración y actuar en consecuencia. Si está realizando una operación de bloqueo en ese hilo, es más o menos SOL porque su hilo está "bloqueando" en la lectura. Eche un vistazo a la respuesta que publiqué here. Así que, básicamente, a menos que sea haciendo un bucle o revisando periódicamente algunos indicadores dentro de ese hilo, no tiene forma de salir sin cerrar los sockets o cosas por el estilo.

Una solución aquí es exponer "explícitamente" el objeto de conexión subyacente y llamar al close(), forzándolo a lanzar algún tipo de excepción, que luego puede ser manejada en el código del hilo. Algo como:

class MyAction extends Thread implements Disposable { 

    public void doStuff() { 
    try { 
     byte[] data = this.connection.readFully(); 
    } catch (InterruptedException e) { 
    // possibly interrupted by forceful connection close  
    } 

    @Override 
    public void dispose() { 
    this.connection.close(); 
    } 
} 

// Elsewhere in code 
MyAction action = conMap.get("something"); 
action.dispose(); 
Cuestiones relacionadas