J'essaie de lire l'entrée d'une socket ligne par ligne dans plusieurs threads. Comment puis-je interrompre readLine()
afin de pouvoir gracieusement arrêter le thread qu'il bloque?
EDIT (bounty) : Cela peut-il être fait sans fermer le socket?
J'essaie de lire l'entrée d'une socket ligne par ligne dans plusieurs threads. Comment puis-je interrompre readLine()
afin de pouvoir gracieusement arrêter le thread qu'il bloque?
EDIT (bounty) : Cela peut-il être fait sans fermer le socket?
Sans fermer la socket:
Le difficile problème n'est pas l' BufferedReader.readLine
, mais le sous-jacent read
. Si un thread est bloqué, la lecture, la seule façon de l'obtenir est de fournir des données réelles ou fermer le socket (interrompant le fil probablement devrait fonctionner, mais dans la pratique, ne prend pas).
Donc, la solution évidente est d'avoir deux fils. Celui qui lit les données brutes, et restera bloquée. La seconde, sera le thread appelant readLine
. Tuyau de données à partir de la première à la seconde. Vous avez alors accès à un verrou qui peut être utilisé pour de réactivation de la deuxième thread, et de prendre les mesures appropriées.
Il y a des variations. Vous pourriez avoir le premier thread à l'aide de NIO, avec un seul thread instance partagée entre tous les consommateurs.
Sinon, vous pourriez écrire un readLine
qui fonctionne avec NIO. Cela pourrait même prendre un relativement simple single-threaded forme, comme en Selector.wakeup
existe et fonctionne.
Je jouais avec cela récemment (en utilisant Scala), et je n'aimais pas la réponse acceptée de fermer le socket et d'obtenir une exception.
Finalement, j'ai découvert qu'il était possible d'appeler socket.shutdownInput()
dans le thread d'interruption pour sortir de l'appel readLine sans exception. Je fais cet appel dans un gestionnaire SIGINT afin de pouvoir nettoyer et fermer le socket dans le thread principal.
Notez que l'équivalent existe pour le flux de sortie avec socket.shutdownOutput()
Je pense que vous devrez peut-être utiliser autre chose que readLine()
. Vous pouvez utiliser read()
et à chaque itération de boucle vérifier pour voir si le thread a été interrompu et sortir de la boucle si c'était le cas.
BufferedReader reader = //...
int c;
while ((c = reader.read()) != -1){
if (Thread.isInterrupted()){
break;
}
if (c == '\n'){
//newline
}
//...
}
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.