thread - ¿Cómo detener un hilo que espera en una operación de lectura de bloqueo en Java?
método utilizado para comenzar la ejecución de un thread (7)
Tengo un hilo que ejecuta el siguiente código:
public void run() {
try {
int n = 0;
byte[] buffer = new byte[4096];
while ((n = in.read(buffer)) != -1) {
out.write(buffer, 0, n);
out.flush();
}
} catch (IOException e) {
System.out.println(e);
}
}
donde in
es System.in
. ¿Cómo puedo detener ese hilo con gracia? Ni el cierre de System.in
, ni el uso de Thread.interrupt
parecen funcionar.
¿Es seguro cerrar en secuencia en otro hilo? Esto funciona para mi. En este caso, in.read(...)
lanza la excepción SocketException
.
Esto se debe a que leer System.in (InputStream) es una operación de bloqueo.
Mira aquí ¿Es posible leer desde un InputStream con un tiempo de espera?
Podría usar el método available () (que no es de bloqueo) para verificar si hay algo para leer de antemano.
En pseudo-java:
//...
while(running)
{
if(in.available() > 0)
{
n = in.read(buffer);
//do stuff with the buffer
}
else
{
Thread.sleep(500);
}
}
//when running set to false exit gracefully here...
Puedes usar una bandera externa para esto
boolean flag = true;
public void run() {
try {
int n = 0;
byte[] buffer = new byte[4096];
while ((n = in.read(buffer)) != -1 && flag) {
out.write(buffer, 0, n);
out.flush();
}
} catch (IOException e) {
System.out.println(e);
}
}
Si desea darle un tiempo a un usuario para ingresar datos, tal vez para permitir anular valores predeterminados o interrumpir algún proceso automatizado, espere primero y verifique la entrada disponible después de la pausa:
System.out.println("Enter value+ENTER within 5 Seconds to override default value: ");
try{
Thread.sleep(5000);
} catch {InterruptedException e){}
try{
int bytes = System.in.available();
if (bytes > 0) {
System.out.println("Using user entered data ("+size+" bytes)");
} else {
System.out.println("Using default value");
}
} catch(IOException e) { /*handle*/ }
Te has topado con un bug 9 años que nadie está dispuesto a solucionar. Dicen que hay algunas soluciones en este informe de error . Lo más probable es que tenga que encontrar otra forma de establecer el tiempo de espera (la espera ocupada parece inevitable).
Tuve el mismo problema hoy, y así es como lo arreglé, usando in.ready()
:
public void run() {
String line;
// Some code
while(!Thread.currentThread().isInterrupted()){
try {
if (in.ready()) {
line = in.readLine();
}
} catch (Exception e) {
try {
Thread.currentThread().wait(500);
} catch (InterruptedException e1) {
// Do what we want when thread is interrupted
}
}
}
}