如何在 Java 中为进程实现超时?
Posted
技术标签:
【中文标题】如何在 Java 中为进程实现超时?【英文标题】:How to implement a timeout for a process in Java? 【发布时间】:2021-07-03 20:38:57 【问题描述】:我想为一个进程实现超时,如果它需要超过 X 秒,我希望它停止并执行 return 语句。 在我的实际使用中,我会调用一个 REST API,apiCallController() 代表控制器。
根据我在下面尝试的所有内容,无论如何都会继续执行。
我该如何解决这个问题?
编辑:如果我想要实现的工作,长时间运行的任务将无法完成,这意味着该行
System.out.println("End http/SSH stuff...");
永远不会打印,而这一行
response = "Call successful...";
也不会执行,将响应变量保留为最初初始化的状态
String response = "Call aborted...";
但我仍然需要在超时后返回响应
我一直在这个 Java fiddle 中进行测试(你可以直接粘贴代码):https://javafiddle.leaningtech.com/
谢谢。
import java.util.*;
import java.lang.*;
public class JavaFiddle
public static void main(String[] args)
String response = apiCallController();
System.out.println(response);
public static String apiCallController()
System.out.println("creepy...\n");
int timeoutSeconds = 2;
int longRunningTaskDurationSeconds = 5;
String response = "Call aborted...";
try
new Timer().schedule(
new TimerTask()
@Override
public void run()
System.out.println("Timeout reached, aborting... (This is where I want everything to stop without killing JVM/Tomcat)");
// System.exit(0); This guy shut tomcat down x_X
return;
,
timeoutSeconds * 1000
);
System.out.println("Start http/SSH stuff...");
Thread.sleep(longRunningTaskDurationSeconds * 1000);
System.out.println("End http/SSH stuff...");
response = "Call successful...";
catch(InterruptedException e)
System.out.println(e);
System.out.println("\npasta...");
return "\n" + response;
编辑 2:根据接受的答案,我只是重构了一点:
import java.util.*;
import java.lang.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ExecutionException;
public class JavaFiddle
public static void main(String[] args)
System.out.println("creepy...\n\n");
String response = apiCallController();
System.out.println(response);
System.out.println("\n\npasta...");
public static String apiCallController()
String response = "Stuff TIMED out...";
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
Callable<String> r = () ->
try
System.out.println("Start http/SSH stuff...");
TimeUnit.SECONDS.sleep(5);
System.out.println("End http/SSH stuff...");
return "Stuff COMPLETED successfully...";
catch (InterruptedException e)
throw e;
;
Future<String> task = executor.submit(r);
try
response = task.get(3, TimeUnit.SECONDS);
catch(InterruptedException | TimeoutException e)
task.cancel(true);
catch (ExecutionException e)
e.printStackTrace();
// Need to shutdown executor (think of it is master thread here)
// You may want to control this behaviour outside of this function call
executor.shutdown();
return "\n" + response;
【问题讨论】:
timeout*1000
是什么?
我正在将秒转换为毫秒。
你见过Asynchronous timeouts with CompletableFutures in Java 8 and Java 9吗?
对了,你可以把timeoutSeconds * 1000
换成更明显的Duration.ofSeconds( timeoutSeconds ).toMillis()
。更好的是,将 timeoutSeconds
的类型更改为名为 timeout
的 Duration
对象。
【参考方案1】:
您的任务在打印到控制台后完成,但您的计时器正在等待更多任务,因此仍在运行,因为它仍在运行,main
函数不会退出。
如果您没有其他任务,您需要cancel
您的计时器。
try
Timer timer = new Timer();
timer.schedule(
new TimerTask()
@Override
public void run()
System.out.println("Timeout reached, aborting... (This is where I want everything to stop without killing JVM/Tomcat)");
,
timeoutSeconds * 1000
);
System.out.println("Start http/SSH stuff...");
Thread.sleep(longRunningTaskDurationSeconds * 1000);
System.out.println("End http/SSH stuff...");
response = "Call successful...";
timer.cancel();
catch(InterruptedException e)
System.out.println(e);
System.out.println("\npasta...");
return "\n" + response;
编辑
由于问题已根据实际用例进行了更新,因此我在此处添加了一个编辑以建议该用例的答案(之前的部分可能与现在的问题无关)。
这是我对您问题的解决方案,看看。我已经使用Future
和ScheduledExecutorService
来实现它。
public static String apiCallController()
System.out.println("creepy...\n");
String response = "Call aborted...";
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
Callable<String> r = () ->
try
// To mimick the actual call
TimeUnit.SECONDS.sleep(5);
System.out.println("call successful...");
return "Some response";
catch (InterruptedException e)
System.out.println("Timeout reached, aborting... (This is where I want everything to stop without killing JVM/Tomcat)");
throw e;
;
Future<String> task = executor.submit(r);
try
System.out.println("Start http/SSH stuff...");
//Let's just wait for 3 secs for response to arrive
response = task.get(3, TimeUnit.SECONDS);
System.out.println("End http/SSH stuff...");
response = "Call successful...";
catch(InterruptedException | TimeoutException e)
// cancelling a task, either it was interrupted (sleep call can be interrupted) or its timeout
task.cancel(true);
catch (ExecutionException e)
//Something went wrong horribly
e.printStackTrace();
System.out.println("\npasta...");
// Need to shutdown executor (think of it is master thread here)
// You may want to control this behaviour outside of this function call
executor.shutdown();
return "\n" + response;
【讨论】:
我试图阻止这些行不执行: System.out.println("End http/SSH stuff..."); response = "调用成功...";.他们仍然使用您的解决方案。 请用此信息更新您的问题,谢谢。以上是关于如何在 Java 中为进程实现超时?的主要内容,如果未能解决你的问题,请参考以下文章
如何在Asp.net Core的登录过程中为“记住我”设置单个cookie超时?
java - 如何在java android中为Gridview的父类BaseAdapter实现viewBinding?