Java 设置方法/线程的最长执行时间

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20500003/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 02:23:00  来源:igfitidea点击:

Setting a maximum execution time for a method/thread

javamultithreadingconcurrency

提问by OneMoreError

I have a method, which writes to the database. The requirement is to make sure that this method does not execute after a certain time elapses. If it returns before that, then nothing should be done.

我有一个方法,它写入数据库。要求是确保该方法在经过一定时间后不执行。如果它在此之前返回,则不应执行任何操作。

The one basic approach that I can think of is doing something like this.

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

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();
        }   
    }
}

One problem with this approach is that even if the method returns before the max total execution time, even then the program halts so as to wait for the time to elapse.

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

How can I do this better (or maybe more correctly) ? And if we use Thread, how can we find out which Threadexecutes that method ?

我怎样才能做得更好(或更正确)?如果我们使用Thread,我们如何找出Thread执行该方法的人?

采纳答案by Andrey Chaschev

You can do this by sending your job to an executor:

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

 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();
    }
}

回答by gvlasov

There is also an AspectJ solution for that with jcabi-aspectslibrary:

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

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

There is an article explaining it further: Limit Java Method Execution Time

有一篇文章进一步解释了它:限制 Java 方法执行时间