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

时间:2019-01-27 18:44:24

标签: java multithreading future

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

main

通常,我会实现一个循环,该循环将不断检查线程是否被中断并最终将其停止。但是,由于线程在Future serverFuture = Executors.newCachedThreadPool().submit(() -> { var serverSocket = new ServerSocket(Config.SERVER_PORT); serverSocket.accept(); // <-- blocking }); serverFuture.cancel(true); 方法中被阻塞,所以这是不可能的。

解决此问题的常用方法是什么?

3 个答案:

答案 0 :(得分:3)

  

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

通常,您不能。但是对于某些特定的操作,您可以做一些事情。例如,您可以尝试中断线程。在您的示例中,如果您无权直接访问运行任务的Thread,则可以使用Future.cancel()

serverFuture.cancel(true);

但是阻塞操作不一定会在其线程发生时被中断。通常,有记录的文件会抛出InterruptedException,而声明为ServerSocket.accept()的异常除外。特别是对于该方法,最好的选择可能是使用ServerSocket.setSoTimeout()accept()阻塞的时间量设置一个合适的上限。使用相对较短的超时并循环执行accept()可以使您定期检查是否中止任务。

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

答案 1 :(得分:0)

在这种情况下,可以使用ServerSocket的close方法来中断accept方法。这将在被接受调用阻塞的线程上抛出SocketException。 (要使用此功能,应使服务器套接字对象在您要取消的位置可访问。)

通常,大多数阻塞api都有一个可以为阻塞调用指定的超时参数。或者可以通过执行线程调用的Thread.interrupt方法来中断它们。

答案 2 :(得分:0)

您需要在调用accept() [1]之前在服务器套接字上设置超时时间:

serverSocket.setSoTimeout(100);

然后,如果它未能在设置的超时时间内接受任何连接,则accept()将抛出SocketTimeoutException,您可以通过中断循环或通过中断来决定是否要继续/停止接受连接。再次致电accept()

[1] https://docs.oracle.com/javase/7/docs/api/java/net/ServerSocket.html#setSoTimeout(int)