Comment arrêter un thread en attente dans une opération de lecture bloquante en Java?
j'ai un thread qui exécute le code suivant:
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);
}
}
où in
System.in
. Comment puis-je arrêter un tel fil avec grâce? Ni de fermeture System.in
, ni à l'aide de Thread.interrupt
semblent fonctionner.
7 réponses
c'est à cause du système de lecture.in (InputStream) est une opération de blocage.
Regarde ici Est-il possible de lire à partir d'un InputStream avec un délai d'attente?
Vous avez trébuché sur un de 9 ans bug personne n'est prêt à les réparer. On dit qu'il y a des solutions de rechange en ce rapport de bogue. Très probablement, vous aurez besoin de trouver un autre moyen de mettre le temps d'arrêt (l'attente occupée semble inévitable).
Vous pouvez utiliser la méthode disponible () (qui n'est pas bloquante) pour vérifier s'il y a quelque chose à lire à l'avance.
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...
j'ai eu le même problème aujourd'hui, et c'est comme ça que je l'ai corrigé, en utilisant 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
}
}
}
}
Est-il sécuritaire de proximité dans les flux dans l'autre thread?
Il fonctionne pour moi. Dans ce cas, in.read(...)
lance l'exception SocketException
.
si vous voulez donner à un utilisateur un certain temps pour entrer des données - peut-être pour autoriser des valeurs par défaut ou interrompre un processus automatisé -, alors attendez d'abord et vérifiez les entrées disponibles après la pause:
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*/ }
vous pouvez utiliser un externe drapeau pour cette
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);
}
}