繁体   English   中英

如何检查函数执行是否超过指定的秒数?

[英]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()方法,这会导致在JSONRequesterrun()方法中抛出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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM