在关机时可靠地关闭线程池中的客户端套接字

时间:2014-08-27 13:34:30

标签: java sockets network-programming threadpool

我有一个简单的基于ServerSocket的java程序,它接受客户端连接并将其放在线程池中(ThreadPoolExecutor):

while() {
    socket = serverSocket.accept();
    pool.submit(new Client(socket)); // Client is a Runnable
}

问题是当我尝试关闭程序并且客户端线程保持不变直到另一端关闭连接时(jvm在此之前不会退出)。

我可以尝试维护所有客户端对象,并在服务器即将关闭时关闭所有套接字。但我不知道如何维护它们?特别是在完成后删除它们。

我尝试了beforeExecute等,但这只给了我另一个对象(FutureTask),而不是我正在寻找的Client对象。

更新

问题不是在列表中添加套接字,问题是在完成后删除它们,因为没有办法(afaik)在执行之后使用它。

3 个答案:

答案 0 :(得分:1)

将所有套接字存储在List中,然后再将其提交到池中。然后关闭线程可以在所有套接字上调用close(),这会导致阻塞的线程抛出SocketException

答案 1 :(得分:1)

一种方法是让客户端完成后返回本身(在将来)。只需要一个列表然后使用afterExecute方法。

像这样:

pool =new ThreadPoolExecutor(...) {
    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        // The future returns the Client object!
        client = (Client)((FutureTask)r).get();
        // Remove it from list of known clients
        clients.remove(client);

    }
};

while() {
    socket = serverSocket.accept();
    Client client = new Client(socket)

    // Submit to pool, using client as the future return value          
    pool.submit(client, client);
    // Add to list of known clients
    clients.add(client);
}

// When app is closing
private shutdown() {
    for(Client client : clients){
        client.shutdown();
    }
}

答案 2 :(得分:0)

在所有客户端套接字上调用shutdownInput()。这将导致关联的线程认为对等体已断开连接,因此优雅地退出。