mr.M
mr.M

Reputation: 899

Unable to shutdown a thread pool

I would like to shutdown a server when countDownLatch.getCount() is zero, but instead of shutting down, it waits on accepting socket connection. Here is the server code that handles incoming TCP requests.

public static void start(File configFile, ReplyListener replyListener, CountDownLatch countDownLatch) {
            try {
                Server.init(configFile);
                while (countDownLatch.getCount() != 0) {
                    //try {
                        Server.socket = serverSocket.accept();
                        Message message = new Message();
                        message.setSocket(Server.socket);
                        Server.pool.submit(new ServerTaskCallable(message.receive()).setReplyListener(replyListener));
                    /*} catch (SocketTimeoutException e){
                        System.out.println("Finished testing");
                    }*/
                }
                Server.socket.close();
                serverSocket.close();
                Server.pool.shutdownNow();
            } catch (IOException e) {
                logger.error("Cannot start a server. The server thread will be terminated. Exception: ", e);
                System.exit(0);
            }
        }

Here is the thread dum:

"pool-1-thread-1@651" prio=5 tid=0xe nid=NA runnable
  java.lang.Thread.State: RUNNABLE
      at java.net.PlainSocketImpl.socketAccept(PlainSocketImpl.java:-1)
      at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:404)
      at java.net.ServerSocket.implAccept(ServerSocket.java:545)
      at java.net.ServerSocket.accept(ServerSocket.java:513)
      at model.server.Server.start(Server.java:42)
      at model.MainTest.lambda$main$3(MainTest.java:30)
      at model.MainTest$$Lambda$2.2012232625.run(Unknown Source:-1)
      at java.lang.Thread.run(Thread.java:745)
      at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
      at java.util.concurrent.FutureTask.run(FutureTask.java:266)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)

"pool-3-thread-1@1142" prio=5 tid=0x12 nid=NA waiting
  java.lang.Thread.State: WAITING
      at sun.misc.Unsafe.park(Unsafe.java:-1)
      at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
      at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
      at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
      at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)

How can I terminate properly the server thread pool?

Upvotes: 2

Views: 759

Answers (1)

Vince
Vince

Reputation: 15146

You have two options:

  1. Set a timeout on the ServerSocket via ServerSocket#setSoTimeout(int). This will cause accept() to throw a SocketTimeoutException everytime the timeout occurs. You will need to catch the exception inside your loop to ensure your server keeps listening for connections:

    while(countDownLatch.getCount() != 0) {
        try {
            socket = serverSocket.accept();
        } catch(SocketTimeoutException e) {
          //timeout occurred!
        }
    }
    
  2. Close the ServerSocket via ServerSocket#close() from a different thread. This will throw a SocketAcception, terminating the accept() call. This exception could be caught outside the loop to easily exit the "listen for connections" behavior.

Upvotes: 1

Related Questions