[英]Best way to implement TimeoutTask
I'm trying to implement a TimeoutTask
which will terminate after a given timeout. 我正在尝试实现一个
TimeoutTask
,它将在给定的超时后终止。 Here is what I have: 这是我所拥有的:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class TimeoutTask {
private Long timeout;
private TimeUnit unit;
public TimeoutTask(Long timeout, TimeUnit unit) {
this.timeout = timeout;
this.unit = unit;
}
public <T> T execute(Callable<T> callable) {
Objects.requireNonNull(timeout, "Timeout");
Objects.requireNonNull(unit, "Time Unit");
Objects.requireNonNull(callable, "Callable");
ExecutorService service =
Executors.newFixedThreadPool(1);
FutureTask<T> task = new FutureTask<T>(callable);
service.execute(task);
try {
return task.get(timeout, unit);
} catch (InterruptedException | ExecutionException | TimeoutException cause) {
if(cause instanceof TimeoutException) {
System.out.println("\nTimeout occured.");
task.cancel(true);
}
} finally {
System.out.println("Finally called.");
service.shutdownNow();
}
return null;
}
public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
Callable<String> callable = () -> {
System.out.print("Enter something: ");
BufferedReader consoleReader =
new BufferedReader(new InputStreamReader(System.in));
String str = consoleReader.readLine();
return str;
};
TimeoutTask timeoutTask = new TimeoutTask(Long.valueOf(10), TimeUnit.SECONDS);
timeoutTask.execute(callable);
}
}
It is working and I can see the message on timeout if there is no input given. 它正在工作,如果没有输入,我可以看到超时消息。 However the process doesn't get terminated.
但是,该过程不会终止。 Following is the screenshot from Eclipse's console, see the highlighted portion:
以下是Eclipse控制台的屏幕截图,请参见突出显示的部分:
When I am giving any input the process terminated immediately. 当我提供任何输入时,该过程将立即终止。 I am calling the
FutureTask#cancel
from the catch block also from finally block I am asking to shutdown the service by making a call to ExecutorService#shoutDownNow
and I can see it is printing that the finally get called. 我从catch块也从finally块调用
FutureTask#cancel
,我要求通过调用ExecutorService#shoutDownNow
来关闭服务,我可以看到它正在打印finally调用。
I am using Java 8 . 我正在使用Java 8 。
Reference: 参考:
In the answer of Marko Topolnik said that the cause is of non-interrupted Java IO; 在Marko Topolnik的回答中,原因是Java IO不受干扰。 so I change the
Callable
as: 所以我将
Callable
更改为:
Callable<Long> callable = () -> {
long i = 0;
for(; i <Long.MAX_VALUE;i++){
}
return i;
};
For this case the same thing happened. 对于这种情况,发生了同样的事情。
Note: The Callable
is just a sample. 注意:
Callable
只是一个示例。
You call 你打电话
String str = consoleReader.readLine();
which means you are using the classic, blocking, non-interruptible Java IO. 这意味着您正在使用经典的,阻塞的, 不间断的 Java IO。 The method keeps blocking even after the timeout and
shutdownNow()
can't touch it, either, because it also just tries to interrupt the thread. 该方法即使在超时和
shutdownNow()
也无法触及它之后仍然保持阻塞,因为它也只是试图中断线程。
BTW I have run your code and the output shows "Finally called". 顺便说一句,我已经运行了您的代码,输出显示为“最终调用”。
Your updated Callable
is just as non-interruptible as the original one. 您更新后的
Callable
与原始Callable
一样不间断。 You must either call a method which declares to throw InterruptedException
(such as Thread.sleep()
) or check Thread.interrupted()
yourself in the loop. 您必须调用一个声明抛出
InterruptedException
的方法(例如Thread.sleep()
),或者自己在循环中检查Thread.interrupted()
。
The issue you need to solve is that System.in.read()
does not response to interrupts. 您需要解决的问题是
System.in.read()
不响应中断。 See how to bypass this in Heinz M. Kabutz newsletter 在Heinz M. Kabutz通讯中了解如何绕过此操作
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.