![](/img/trans.png)
[英]Fallback to methodB if methodA execution takes more than X seconds in Spring Boot
[英]How do I check if function execution takes more than specified seconds?
如果需要超过3秒,我想超时执行一个函数。
long startTime = System.currentTimeMillis();
getStaticJsonResponse("build", "post");
long finishTime = System.currentTimeMillis();
long elapsedTime = finishTime - startTime / 1000;
System.out.println("time" + elapsedTime);
您需要有一个单独的线程,等待方法终止或超时。 幸运的是,伟大的Guava库的创建者已经实现了这一点:只需使用TimeLimiter (在您的情况下, SimpleTimeLimiter )。
您的代码如下所示:
TimeLimiter limiter = new SimpleTimeLimiter();
String result = limiter.callWithTimeout(new Callable<String>() {
public String call() {
return getStaticJsonResponse("build", "post");
}
}, 3, TimeUnit.SECONDS, false);
(假设您的方法返回一个String,否则调整返回类型)。
请注意,与其他解决方案一样,这可以保证呼叫者最多等待3个时间段。 但它确实不能保证方法执行在3秒后实际中止。 只有当被调用的代码对Thread.interrupt()
所做的线程中断做出反应时,它才会被中止。 等待I / O的所有函数都这样做,但您自己的代码可能没有。
我不确定我是否正确地解释了这个问题(因为其他答案另有说明),但我收集到你想要在你的getStaticJsonResponse()
调用上实现超时(我假设它是一个阻塞网络)呼叫)?
如果确实如此,那么这不是一项简单的任务 - 在同步API之上实现超时并不一定容易。
一种方法是使用任务线程。 在这种情况下,您将创建一个类如下的新类:
class JSONRequester implements Runnable
{
@Override
public void run ( )
{
getStaticJsonResponse("build", "post");
}
}
这基本上只是声明了一个可以在单独的线程上运行getStaticJsonResponse()
的类。 然后原始线程可以自由监视任务线程并在运行时间过长时终止它。
要实现超时(例如,3秒),您可以执行以下操作:
...
// Create and start the task thread.
Thread taskThread = new Thread(new JSONRequester ( ));
taskThread.start( );
// Wait 3 seconds.
sleep(3000);
// If after waiting 3 seconds the task is still running, stop it.
if (taskThread.isAlive( ))
taskThread.interrupt( );
...
这里,主线程启动任务线程,后者又调用getStaticJsonResponse()
方法。 然后它等待三秒钟,并检查线程是否仍在运行。 如果线程正在运行(即getStaticJsonResponse()
还没有完成),它会调用线程的interrupt()
方法,这会导致在JSONRequester
的run()
方法中抛出InterruptedException
,从而终止任务线程。
编辑:我应该注意,这假设了一些getStaticJsonResponse()
的代码,特别是,线程阻塞的地方满足此处列出的响应interrupt()
调用的条件之一。 但是,在网络代码中(如图所示),这通常是一个非常安全的假设。
创建一个Timeout
类。 使用表示所需秒数的参数构造它。 给它一个HasTimedOut
成员函数。 在函数中定期调用此成员,如果返回true
,则从函数返回。
如果要处理长时间运行的任务可能需要超过3秒并且需要停止的情况,则应该在单独的线程中执行长时间运行的任务。 最简单的方法是使用Java的Executor框架。
这是一个在线程中运行可能很长(无限长)运行任务的基本示例,然后在运行超过三秒时将其计时。
public static void main(String[] args) {
System.err.println("Start");
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(longRunningTask);
try {
executor.awaitTermination(3, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println("Time up - finished? " + executor.isTerminated()); //false
executor.shutdownNow(); //runnable thread will be interrupted
}
private static Runnable longRunningTask = new Runnable() {
@Override
public void run() {
while (true) {
// ... do some long running task
//periodically check whether task should be aborted
if (Thread.currentThread().isInterrupted()) { //triggered by executor.shutdownNow() above
break; //stop long running task
}
}
}
};
请注意,这不会是3秒(但对于基本超时足够接近),并且在现实世界的情况下,检查中断应该真正检查是否已设置某些(线程安全,即易失性)变量因为中断可能是从另一个线程触发的(但这超出了这个答案的范围)。
只是改变
long elapsedTime = finishTime - startTime / 1000;
至
long elapsedTime = (finishTime - startTime) / 1000;
这应该工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.