Concentration sur un pool de threads en Java

Je fais face à ce problème en Java. J’ai une classe de serveur nommée MyServer et je veux implémenter un pool de threads dans lequel chaque thread exécute une méthode de MyServer lorsqu’une demande arrive. J’ai créé une autre classe qui implémente un pool de serveurs nommé MultiThreadedSocketServer. La classe est la suivante:

public class MultiThreadedSocketServer { public void startServer(MyServer s, int localport, int threadPoolSize) { final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(threadPoolSize); Runnable serverTask = new Runnable() { @Override public void run() { try { ServerSocket serverSocket = new ServerSocket(localport); System.out.println("Waiting for clients to connect..."); while (true) { Socket clientSocket = serverSocket.accept(); clientProcessingPool.submit(new ClientTask(clientSocket, s)); } } catch (IOException e) { System.err.println("Unable to process client request"); e.printStackTrace(); } } }; Thread serverThread = new Thread(serverTask); serverThread.start(); } } 

la classe nommée MultiThreadedSocketServer a un argument nommé Server s qui le transmet dans la classe de tâches cliente à laquelle un thread est créé. La classe de tâches client est la suivante:

  class ClientTask implements Runnable { private final Socket clientSocket; private MyServer s; public ClientTask(Socket clientSocket, MyServer s) { this.s = s; this.clientSocket = clientSocket; } @Override public void run() { System.out.println("Got a client !"); Ssortingng inputLine = null; try { BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); // Do whatever required to process the client's request inputLine = in.readLine(); if (inputLine.equals("Bye")) { System.out.println("Bye"); System.exit(0); } s.handleRequest(inputLine); clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } 

Comme vous pouvez le voir quand une requête arrive, la méthode handleRequest de la classe MyServer est invoquée. Je veux que cette méthode soit synchronisée, ce qui signifie qu’un seul thread à la fois peut exécuter cette méthode. L’ajout synchronisé avant l’implémentation de la méthode n’aboutit à rien.

Quelqu’un peut-il me donner la bonne façon de le faire? Merci d’avance pour votre temps.

PS: j’ai ajouté le code entier

MyServer Class http://pastebin.com/6i2bn5jj

Classe de serveur multithread http://pastebin.com/hzfLJbCS

Comme il est évident dans main, je crée trois requêtes avec handleRequest avec des arguments Task, task2 et Bye.

La sortie correcte serait

 Waiting for clients to connect... Got a client ! This is an input Task Request for Task Got a client ! This is an input task2 Request for task2 Got a client ! This is an input Bye 

Mais au lieu de cela l’ordre est mélangé. Parfois, Bye qui ferme le serveur peut être exécuté en premier. Je veux m’assurer que l’ordre est celui où les demandes sont créées dans la main.

    Mais au lieu de cela l’ordre est mélangé. Parfois, Bye qui ferme le serveur peut être exécuté en premier. Je veux m’assurer que l’ordre est celui où les demandes sont créées dans la main.

    Vous dites que vous voulez que le serveur gère les requêtes dans l’ordre. C’est difficile à garantir car vous ouvrez 3 sockets et les écrivez sur le serveur mais n’attendez aucune réponse. Cela dépend de l’implémentation, mais je ne suis pas sûr que lorsque le client revient de faire une écriture sur un socket, le serveur a reçu les octets. Cela signifie que du côté du client, rien ne garantit que l’OE se termine dans l’ordre que vous souhaitez.

    Pour voir si c’est le problème, je supprimerais le System.exit(0) pour voir si les autres lignes le font, juste après la chaîne "Bye" . Ou vous pourriez mettre un Thread.sleep(5000); avant la exit(0) .

    Une sorte de solution simple serait de vous assurer que la fonction de PrintStream automatique de votre PrintStream est activée. Cela au moins appellera flush sur le socket mais même dans ce cas, il y a des conditions de concurrence entre le client et le serveur. Si le vidage automatique ne fonctionne pas, votre client attendra une réponse du serveur. Ainsi, le premier client écrirait la première commande et attendrait l’accusé de réception avant de passer à la deuxième commande.

    En termes de votre question initiale, le locking sur le serveur ne serait pas utile en raison des conditions de course. Le "Bye" peut le faire en premier et verrouiller le serveur correctement.

    Ce genre de questions sur la façon de synchroniser les threads dans un programme multi-thread n’a vraiment aucun sens pour moi. L’ intérêt des threads est qu’ils s’exécutent de manière asynchrone en parallèle et qu’ils ne doivent pas fonctionner dans un ordre particulier. Plus vous forcez votre programme à cracher la sortie dans un ordre particulier, plus vous argumentez pour écrire ceci sans aucun thread.

    J’espère que cela t’aides.

    Si le problème est que le message bye tue le serveur avant que d’autres requêtes puissent être traitées, une solution pourrait être de ne pas appeler System.exit(0); au bye .

    Le message bye pourrait définir un bloc de drapeau pour d’autres demandes de traitement et notifier à un autre mécanisme d’appeler System.exit(0); lorsque le pool de threads est inactif sans aucune requête à traiter.