首页 > 解决方案 > 如何优雅地停止正在运行阻塞操作的线程?

问题描述

我在需要停止的线程中运行了一个阻塞操作:

Future serverFuture = Executors.newCachedThreadPool().submit(() -> {
    var serverSocket = new ServerSocket(Config.SERVER_PORT);

    serverSocket.accept(); // <-- blocking
});

serverFuture.cancel(true);

通常,我会实现一个循环来不断检查线程是否被中断并最终停止它。但是,由于线程在serverSocket.accept()方法中被阻塞,这是不可能的。

克服这个问题的通常方法是什么?

标签: javamultithreadingfuture

解决方案


如何优雅地停止正在运行阻塞操作的线程?

一般来说,你不能。但是对于某些特定的操作,您可以做一些事情。例如,您可以尝试中断线程。在例如您的示例的情况下,您无法直接访问Thread运行任务的位置,您可以使用Future.cancel()

serverFuture.cancel(true);

但是阻塞操作不一定会在它们的线程中断时被中断。那些通常记录为 throw InterruptedException,并且不在异常中的那些ServerSocket.accept()被声明为 throw。特别是对于该方法,您最好的选择可能涉及使用为将阻塞ServerSocket.setSoTimeout()的时间量设置一个合适的上限。accept()使用相对较短的超时并accept()在循环中执行将允许您定期检查是否中止任务。

总的来说,您需要选择适合您要取消的工作的策略,并且您可能需要花费一些设计精力来使该任务完全可中断。


推荐阅读