【发布时间】:2017-09-09 11:29:25
【问题描述】:
我需要对零循环的长时间运行函数进行时间限制。我使用Callable 运行该函数,并在未来使用超时值调用get。 AFAIU,future.cancel(true) 将为函数线程设置中断标志。但是,除非我在longRunningFunction() 中检查并处理 Thread.isInterrupted(),否则我的代码将不知道它必须退出,即使在shutdownNow() 之后,该函数也不会终止。
- 如何检查
longRunningFunction()中的中断?检查需要提示,即如果在特定点进行检查,那么在这些点被命中之前,线程将不会处理中断。 - 还有其他优雅的方式来限制时间功能吗?
- 为什么我不能直接杀死执行器池中的所有线程?根据JavaDocs for ExecutorService,在线程处理中断并自行终止之前,池永远不会终止。
public class Test {
public void longRunningFunction() {
/*
Long running code without loop
*/
}
public Void call() {
try {
longRunningFunction()
} catch (InterruptedException exception) {
logger.error("{} Error : {}", TAG, exception.getStackTrace().join("\n"))
} catch (Exception exception) {
logger.error("[call]{} Error : {}", TAG, exception.getStackTrace().join("\n"))
}
}
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor()
Future<Void> future = executor.submit(new Test())
int timeoutSeconds = 5
println "Setting timeout to " + timeoutSeconds
try {
future.get(timeoutSeconds, TimeUnit.SECONDS)
} catch (TimeoutException e) {
future.cancel(true)
logger.error("Could not finish processing within {} seconds", timeoutSeconds)
} finally {
executor.shutdownNow()
executor.awaitTermination(3, TimeUnit.SECONDS)
logger.error("Shutting down")
}
}
}
编辑
与标记重复相关的问题表明共享变量是要走的路,这是问题中提到的一个已知事实。问题是如何无缝检查该布尔标志,即Thread.isInterrupted。
【问题讨论】:
-
即使
longRunningFunction没有循环也不可能在此函数内部没有检查中断标志的中间步骤。 -
提到的链接表明共享变量(这里的
isInterrupted标志)是要走的路。这是一个众所周知的事实。问题是如何无缝检查该布尔变量。 -
你说,“没有循环。”我认为这意味着没有循环也没有递归(即,没有一个地方可以放置一个在长期内将执行多次的语句。)而且,我认为它不会调用任何阻塞函数,因为阻塞函数会抛出
InterruptedException.那么还剩下什么?如果一个函数调用没有循环、没有递归、不调用任何阻塞函数,它的调用需要多长时间? -
好的,我被正式取消了提供更多 Java 建议的资格。从任何类型的
InputStream读取时,似乎无法获得InterruptedException。听起来您的InputStream是从Socket获得的。如果一个线程关闭套接字而另一个线程正在等待接收字节会发生什么?
标签: java multithreading executorservice