beld
beld

Reputation: 81

Java ExecutorService can't shutdown with executing Server

I'm not sure what exactly the problem is with shutting down my Server (and ExecutorService). I start the ServerMain and press enter, which starts the server.shutdown() method with socket.close() but it doesn't throw a SocketException. I don't know if this is related to the ExecutorService not being able to shutdown though. This is the code:

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

And here's the server:

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

Upvotes: 0

Views: 628

Answers (3)

nucleus
nucleus

Reputation: 43

In your TCPDirectoryServer class make serverSocket a member variable and your shutdown method should look like the following

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

Also when closing a client socket(s) watch out for NPE if the socket is null (no one connected to your server). This will also prevent your server from shutting down.

Upvotes: 0

Ted
Ted

Reputation: 1690

Calling the serverExecutor.shutdown() will still cause the server to wait for all processes to finish before shutting down. It's a gracefully shutdown. It is probably waiting on the "while(true)" loop to exit, which it doesn't look like it ever will. Try calling serverExecutor.shutdownNow(); to terminate your program.

Upvotes: 0

john16384
john16384

Reputation: 8044

This part:

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

...won't throw a SocketException when you call shutdown, because you're closing a client socket there (the one that last connected). The ServerSocket is still open and waiting for incoming requests.

Upvotes: 2

Related Questions