java - 如何优雅地停止正在运行阻塞操作的线程?
问题描述
我在需要停止的线程中运行了一个阻塞操作:
Future serverFuture = Executors.newCachedThreadPool().submit(() -> {
var serverSocket = new ServerSocket(Config.SERVER_PORT);
serverSocket.accept(); // <-- blocking
});
serverFuture.cancel(true);
通常,我会实现一个循环来不断检查线程是否被中断并最终停止它。但是,由于线程在serverSocket.accept()
方法中被阻塞,这是不可能的。
克服这个问题的通常方法是什么?
解决方案
如何优雅地停止正在运行阻塞操作的线程?
一般来说,你不能。但是对于某些特定的操作,您可以做一些事情。例如,您可以尝试中断线程。在例如您的示例的情况下,您无法直接访问Thread
运行任务的位置,您可以使用Future.cancel()
:
serverFuture.cancel(true);
但是阻塞操作不一定会在它们的线程中断时被中断。那些通常记录为 throw InterruptedException
,并且不在异常中的那些ServerSocket.accept()
被声明为 throw。特别是对于该方法,您最好的选择可能涉及使用为将阻塞ServerSocket.setSoTimeout()
的时间量设置一个合适的上限。accept()
使用相对较短的超时并accept()
在循环中执行将允许您定期检查是否中止任务。
总的来说,您需要选择适合您要取消的工作的策略,并且您可能需要花费一些设计精力来使该任务完全可中断。
推荐阅读
- c# - 将内容添加到列表
- json.net - JSON 值无法转换为 Newtonsoft.Json.Linq.JToken。路径:$ | 行号:1 | 字节位置行内:8
- javascript - 如何通过单击将项目移动到另一个组件 - vue.js
- json - Flutter json解码返回null
- java - 使用正确的 remove() 方法时显示 java.util.ConcurrentModificationException
- c# - .NET API 控制器为 AJAX POST 返回 405
- jquery - jQuery追加不显示每个方法的html
- javascript - 如何解决 Vue.js 中多个根元素的限制?
- python-3.7 - 为什么尝试从两个 ZeroMQ 套接字读取消息的代码会失败?
- java - Android Studio Fragment RoomListFragment 未附加到 Activity(在导航抽屉中启动新活动)