【问题标题】:Setting a maximum execution time for a method/thread设置方法/线程的最大执行时间
【发布时间】:2013-12-10 16:35:36
【问题描述】:

我有一个写入数据库的方法。要求是确保此方法在经过一定时间后不执行。如果它在那之前返回,那么什么都不应该做。

我能想到的一种基本方法是做这样的事情。

public class LimitedRuntime {

    public static void writeToDb(){
            // writes to the database
    }

    public static void main(String[] args) {
        long totalExecutionTime = 8000L;
        long startTime = System.currentTimeMillis();

        while(System.currentTimeMillis() - startTime < totalExecutionTime )
        {
            writeToDb();
        }   
    }
}

这种方法的一个问题是,即使方法在最大总执行时间之前返回,即使如此,程序也会暂停以等待时间过去。

我怎样才能做得更好(或者更正确)?如果我们使用Thread,我们如何找出哪个Thread执行了那个方法?

【问题讨论】:

  • 什么是最不经意的解决方案,Δt = t2 - t2o.O

标签: java multithreading concurrency


【解决方案1】:

您可以通过将您的工作发送给执行者来做到这一点:

 public static void main(String[] args) {
    ExecutorService executor = Executors.newFixedThreadPool(4);

    Future<?> future = executor.submit(new Runnable() {
        @Override
        public void run() {
            writeToDb();            //        <-- your job
        }
    });

    executor.shutdown();            //        <-- reject all further submissions

    try {
        future.get(8, TimeUnit.SECONDS);  //     <-- wait 8 seconds to finish
    } catch (InterruptedException e) {    //     <-- possible error cases
        System.out.println("job was interrupted");
    } catch (ExecutionException e) {
        System.out.println("caught exception: " + e.getCause());
    } catch (TimeoutException e) {
        future.cancel(true);              //     <-- interrupt the job
        System.out.println("timeout");
    }

    // wait all unfinished tasks for 2 sec
    if(!executor.awaitTermination(2, TimeUnit.SECONDS)){
        // force them to quit by interrupting
        executor.shutdownNow();
    }
}

【讨论】:

  • 在中断线程时,你必须记住,你必须添加一个条件,比如if (isInterrupted()) { return; }。没有这个,线程根本不会被中断!不知道它如何与 Runnable 接口一起工作......
  • 是的,我认为数据库驱动程序应该支持这个。
  • 我不熟悉ExecutorService。我会读到它。顺便说一句,你能告诉我 a) 如果方法在最大时间过去之前完成并返回,上面会发生什么? b)一旦超过时间限制,我想立即终止该方法。为此,我应该使用executor.awaitTermination(0, TimeUnit.SECONDS) 吗?
  • a) 未来停止等待作业完成,main() 线程继续执行。在这种特殊情况下,应用程序将简单地退出。 b) future.cancel(true) 应该终止线程。正如@bobbel 指出的那样,线程需要支持终止。您的数据库驱动程序应该支持它,如果线程执行多个请求,它应该检查它们之间的Thread.interrupted() 标志。
【解决方案2】:

还有一个带有 jcabi-aspects 库的 AspectJ 解决方案:

@Timeable(limit = 5, unit = TimeUnit.SECONDS)
public String writeToDb() {
  // writeToDb
}

有一篇文章进一步解释:Limit Java Method Execution Time

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-06
    • 1970-01-01
    • 2011-07-04
    相关资源
    最近更新 更多