2017-01-10 2 views
0

Je ne sais pas exactement quel est le problème avec l'arrêt de mon serveur (et ExecutorService). Je démarre le ServerMain et appuyez sur Entrée, ce qui démarre la méthode server.shutdown() avec socket.close() mais il ne lance pas une exception SocketException. Je ne sais pas si cela est lié au fait que l'ExecutorService ne puisse pas s'arrêter. Voici le code:Java ExecutorService ne peut pas s'arrêter avec l'exécution du serveur

public class ServerMain { 

public static void main(String[] args) throws DirectoryServerException, IOException { 
    TCPDirectoryServer server = new TCPDirectoryServer(); 
    ExecutorService serverExecutor = Executors.newSingleThreadExecutor(); 
    try { 
     server.start(1337); 
     serverExecutor.execute(server); 
     System.out.println("Server started. Press enter to terminate."); 

     System.in.read(); 

     server.shutdown(); 
     System.out.println("Server is shut down..."); 
    } finally { 
     serverExecutor.shutdown(); 
     while (!serverExecutor.isTerminated()) { 
      try { 
       if (!serverExecutor.awaitTermination(5, TimeUnit.SECONDS)) { 
        System.err.println("Problem with shutting down the Executor"); 
        serverExecutor.shutdownNow(); 
       } 
      } catch (InterruptedException ignore) { 
      } 
     } 
    } 
} 
} 

Et voici le serveur:

public class TCPDirectoryServer implements DirectoryServer { 
private int port; 
private ConcurrentHashMap<ParseDirectory, Histogram> cache; 
private List<ClientHandler> clientHandlerList; 
private ExecutorService clientExecutorService; 
private Socket socket; 

public TCPDirectoryServer() { 
    super(); 
    this.cache = new ConcurrentHashMap<ParseDirectory, Histogram>(); 
    this.clientHandlerList = new LinkedList<ClientHandler>(); 
    this.clientExecutorService = Executors.newCachedThreadPool(); 
} 

@Override 
public void start(int port) throws DirectoryServerException { 
    this.port = port; 
} 

@Override 
public void disconnect(ClientHandler clientHandler) { 
    clientHandlerList.remove(clientHandler); 

} 

@Override 
public void shutdown() throws DirectoryServerException { 
    try { 
     socket.close(); 
    } catch (IOException e) { 
     throw new DirectoryServerException(e); 
    } 
} 

@Override 
public void run() { 
    try (ServerSocket serverSocket = new ServerSocket(port)) { 
     while (true) { 
      socket = serverSocket.accept(); 
      clientHandlerList.add(connect(socket)); 
     } 
    } catch (SocketException e) { 
     System.err.println("AAAA"); 
     System.out.println("Server is shutting down"); 

    } catch (IOException e) { 
     System.out.println("Something failed " + e.getMessage()); 
    } 
} 

Répondre

2

Cette partie:

while (true) { 
     socket = serverSocket.accept(); 
     clientHandlerList.add(connect(socket)); 
    } 

... ne jetterai pas SocketException lorsque vous appelez shutdown, parce que vous fermez une socket client là (celle qui s'est connectée en dernier). ServerSocket est toujours ouvert et en attente des demandes entrantes. L'appel de serverExecutor.shutdown() entraînera toujours le serveur à attendre que tous les processus se terminent avant de s'arrêter.

0

C'est un arrêt gracieux. Il attend probablement sur la boucle "while (true)" pour quitter, ce qui ne semble pas le cas. Essayez d'appeler serverExecutor.shutdownNow(); pour terminer votre programme.

0

Dans votre marque de classe TCPDirectoryServer serverSocket une variable membre et votre méthode d'arrêt devrait ressembler à ce qui suit

public void shutdown() { 
    ...... 
    this.serverSocket.close(); 
    ........ 
} 

également lors de la fermeture d'un socket client (s) attention NPE si la prise est nulle (pas un connecté à votre serveur). Cela empêchera également votre serveur de s'arrêter.