我正在使用ExecutorService进行连接任务,如下所示:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<ApplicationConnection> future = (Future<ApplicationConnection>) executor.submit(new ConnectThread(crf, connoptions));
connection = future.get(300000, TimeUnit.SECONDS);
executor.shutdownNow();
call()
方法调用.connect()
方法(专有API)。这种连接方法产生了各种线程池等。我担心的是,如果将来超时并杀死执行程序,将来通过调用.connect()
方法生成的线程是否也会结束?我知道杀死一个线程也会杀死任何子线程,但这是否遵循相同的逻辑?
你的假设是正确的,如果Future
超时,一些悬挂的线程将保留。更糟糕的是,shutdownNow()
甚至不会关闭你的池线程(更不用说专有的API线程)了。它只是停止接受新的工作。一旦所有正在运行的任务完成,ExecutorService
线程池将终止所有线程。
你可以做的是尝试取消未来并打断它。首先处理你未来的InterruptedException
:
class ConnectThread implements Callbale<ApplicationConnection> {
public ApplicationConnection call() {
try {
return prioprietaryApi.connect();
} catch(InterruptedException e) {
prioprietaryApi.cleanUp();
throw e;
}
}
}
现在只需运行:
future.cancel(true);
但是,您的专有API可能无法处理InterruptedException
(它不会从connect()
重新抛出它,而且您可能无法访问任何cleanUp()
方法。
在这种情况下,只是......忘记它。 Future
最终将终止并清理自己,忽略了你不再等待它的事实。当然,这可能会导致各种可伸缩性问题。
顺便说一下,如果您想要实现的唯一目标是限制给定方法运行的最大时间,请考虑来自TimeLimiter
的guava。
根据javadoc
尝试停止所有正在执行的任务,停止等待任务的处理,并返回等待执行的任务列表。除尽力尝试停止处理主动执行任务之外,没有任何保证。例如,典型的实现将通过Thread.interrupt()取消,因此任何未能响应中断的任务都可能永远不会终止。