Voici un extrait d'un serveur Web que je suis en train de construire ...comportement avec plusieurs threads Peculiar/variables volatiles/boucles/conditionals (Java)
// ...
threadPool = Executors.newCachedThreadPool(); while (true) if(this.isOn) { try { // listen for incoming connection this.clientSocket = serverSocket.accept(); } catch (IOException e) { System.err.println("LOG: >> Accept failed! "); System.exit(1); } // as soon as a connection is established send the socket // with a handler/processor to the thread pool for execution threadPool.execute(new ClientRequestProcessor(clientSocket)); }
// ...
Veuillez noter que la variable isOn est un booléen VOLATILE.
Si j'allume le si dans un certain temps ... ce code fonctionne ... mais comme il est pas. Puis-je demander pourquoi? D'un point de vue logique, les deux devraient fonctionner, même si je teste ce drapeau dans un si ... ai-je raté quelque chose ?!
[Modification postérieure:] En ne fonctionnant pas, je veux dire ... un navigateur (par exemple firefox) ne peut pas se connecter, en fait il continue à essayer mais il finira par s'arrêter. Encore une fois, si je change ça si (isOn) en un temps (isOn) cela fonctionne comme un charme.
Toutes les suggestions/idées sont plus que bienvenues !!!
P.S. J'ai besoin de ce combo "while (true) if/while (drapeau de test) {...}" parce que le serveur peut être démarré/arrêté à partir d'une interface graphique ... donc le niveau supérieur alors que (vrai) est nécessaire peut revérifier si je suis sur (et donc écouter les connexions) ou si je suis éteint (et ne se soucient pas vraiment des connexions entrantes). Les aiguilles indiquant que les gestionnaires d'événements de l'interface graphique peuvent modifier le drapeau à tout moment.
Je suis complètement d'accord avec ce que vous avez dit. De plus, vous avez raison de dire que le changement de drapeau à false garantit encore une autre "écoute d'une connexion" avant que le serveur "arrête de servir". Mais cela n'explique toujours pas le comportement erratique que j'obtiens avec la version actuelle du code! Je vais probablement adopter votre solution, mais je suis toujours curieux de savoir pourquoi une version fonctionne et l'autre ne fonctionne pas ... alors que les deux devraient logiquement l'être. Les questions n'étaient pas vraiment s'il y a une meilleure solution (vous avez déjà prouvé qu'il existe!) Mais plutôt pourquoi ce code Java se comporte-t-il si maladroitement ... – Tibbers
@Tibi, while (true) if (flag) et while (true) alors que (drapeau) devrait être identique dans votre cas. Je soupçonne que votre test n'est pas stable reproductible. –
Encore une fois, vous pourriez avoir raison sur celui-ci aussi. Parce que si j'exécute le if-variant avec le débogueur et que j'exécute le code ligne par ligne alors ça marche parfaitement ... cependant si je viens de lancer run et de le laisser seul le if-variant ne fonctionne pas! Donc, en effet, je ne peux probablement pas reproduire l'état réel de la machine, rendant ainsi toute tentative de comprendre ce comportement maladroit futile. Quoi qu'il en soit, merci pour les réponses rapides ... votre proposition (initiale) de refactoring/redesign a déjà été implémentée et fonctionne comme un charme! – Tibbers