2011-02-13 20 views
5

Estoy usando un entorno multihilo donde un hilo de rosca escucha constantemente la entrada del usuario al llamar repetidamente al scanner.nextLine(). Para finalizar la aplicación, este subproceso se detiene con otro subproceso, pero el subproceso de escucha no se detiene hasta que se realizó una última entrada de usuario (debido a la naturaleza de bloqueo de nextLine()).Cómo interrumpir llamada java.util.Scanner nextLine

El cierre de la secuencia no parece ser una opción ya que estoy leyendo System.in, que devuelve InputStream que no se puede cerrar.

¿Hay alguna forma de interrumpir el bloqueo del escáner para que vuelva?

gracias

+0

puede llamar a 'scanner.hasNext()' en lugar de 'scanner.nextLine()' este método ** puede ** bloquearse de acuerdo con javadoc, por lo tanto, es posible que necesite manejar eso. La idea es que a diferencia de 'scanner.nextLine()', 'scanner.hasNext()' no avance la entrada, por lo que puede verificar un indicador si el hilo de lectura ha sido detenido por otro hilo antes de llamar a 'scanner.nextLine () ' –

+1

sí, pero esto implicaría un sondeo constante. –

+0

Debería poder llamar a Thread.interrupt en el hilo de escucha, esto causaría una InterruptedIOException que puede obtener del método ioException(). No estoy seguro de cómo interactúa con nextLine() o si funciona con su inputstream subyacente, pero debe terminar nextLine en la mayoría de los casos. – josefx

Respuesta

8

Este article describe un método para evitar el bloqueo de la lectura. Proporciona el fragmento de código, que puede modificar como lo indico en un comentario.

import java.io.*; 
import java.util.concurrent.Callable; 

public class ConsoleInputReadTask implements Callable<String> { 
    public String call() throws IOException { 
    BufferedReader br = new BufferedReader(
     new InputStreamReader(System.in)); 
    System.out.println("ConsoleInputReadTask run() called."); 
    String input; 
    do { 
     System.out.println("Please type something: "); 
     try { 
     // wait until we have data to complete a readLine() 
     while (!br.ready() /* ADD SHUTDOWN CHECK HERE */) { 
      Thread.sleep(200); 
     } 
     input = br.readLine(); 
     } catch (InterruptedException e) { 
     System.out.println("ConsoleInputReadTask() cancelled"); 
     return null; 
     } 
    } while ("".equals(input)); 
    System.out.println("Thank You for providing input!"); 
    return input; 
    } 
} 

Usted podría utilizar este código directamente, o escribir una nueva clase InputStream, con cierre, terminando la lógica descrita en este artículo.

+2

Hola, gracias, esperaba una solución que no implique espera activa. –

0

Sure. Usa una bomba nuclear Llame al System.exit(0) al final de su hilo principal. Esto matará a todo. Incluso el hilo activo está esperando en System.in.

El problema es que System.in es un flujo de entrada tradicional con bloqueo, y cuando está bloqueando el hilo se marca como en ejecución. No puedes interrumpirlo. Entonces, cualquier hilo que esté usando para leer System.in está llamando a read y la lectura bloqueará el hilo. Puedes convencer a algunas de estas cosas con un montón de trucos para evitar llamar a leer, excepto en aquellos casos en los que podemos estar seguros de que no habrá bloqueo y luego sondear constantemente. Sin embargo, no existe una solución real al problema que cualquier intento de lectura bloqueará el hilo y no se ahorrará ninguna cantidad de secuencias subyacentes cerradas o interrumpiendo o deteniendo el hilo. Pero, si asesinas a toda vm ... el hilo morirá.

Obviamente necesitas asegurarte de que el resto de los hilos hayan salido correctamente y es solo eso estúpido Quiero poder responder al hilo de entrada mecanografiado que es el último enganche. Pero, si ese es el caso, la respuesta correcta es salir, o al menos, básicamente la única respuesta que funcionará sin grabar ciclos de reloj sin ninguna razón y dejar que el programa finalice.

+2

De hecho, probé esto, y 'System.exit (0)' no lo detuvo de manera sorprendente. Tuve que 'matar -9' el proceso. Incluso 'killall java' no funcionó. – Arin

+0

Funcionó para mí. Pero, lamentablemente con este fallo/error, creo que podría ser inmune al arma nuclear. – Tatarize

Cuestiones relacionadas