2017-01-10 3 views
0

Я не уверен, в чем проблема с выключением моего Сервера (и ExecutorService). Я запускаю ServerMain и нажимаю Enter, который запускает метод server.shutdown() с socket.close(), но не вызывает исключение SocketException. Я не знаю, связано ли это с тем, что ExecutorService не может завершить работу. Это код:Java ExecutorService не может завершить работу с выполнением сервера

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) { 
      } 
     } 
    } 
} 
} 

И вот сервер:

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()); 
    } 
} 

ответ

2

Эта часть:

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

... не будет бросать SocketException, когда вы звоните shutdown, потому что вы закрываете клиентский сокет там (тот, который последний подключен). ServerSocket все еще открыт и ожидает входящих запросов.

0

Вызов сервераExecutor.shutdown() все равно заставит сервер ждать завершения всех процессов до завершения. Это изящное закрытие. Вероятно, он ждет цикла while (true), чтобы выйти, что не похоже на то, что он когда-либо будет. Попробуйте вызвать serverExecutor.shutdownNow(); для завершения вашей программы.

0

В вашем классе TCPDirectoryServer марки ServerSocket переменную-член и ваш метод завершения работы должен выглядеть следующим образом

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

Также при закрытии клиента разъем (ы) следить за NPE, если сокет является нулевым (никто подключен к вашему серверу). Это также предотвратит останов вашего сервера.