简体   繁体   English

限制Java中方法的执行时间

[英]to restrict the execution time of method in java

I want to restrict the execution time of a method in java, I want my particular method that If it is executed in some certain defined time then ok otherwise it should throw an exception. 我想限制Java中某个方法的执行时间,我希望我的特定方法是:如果它在某个确定的时间内执行,那么可以,否则它将引发异常。

For this I tried using as : 为此,我尝试使用as:

@Timeable(limit = 1000, unit = TimeUnit.MILLISECONDS)
public void testMethod(){
    try {
            Thread.sleep(2000);
            if (Thread.interrupted()) {
                  throw new InterruptedException();
            }
        }catch(InterruptedException e1){
            logger.error("failed due to-" + e1, e1.getMessage());
            throw new InterruptedException(e1.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new Exception(e.getMessage());
        }
}

For this I took reference from : http://www.yegor256.com/2014/06/20/limit-method-execution-time.html 为此,我从以下网站获取了参考: http : //www.yegor256.com/2014/06/20/limit-method-execution-time.html

It should throw the exception after the line: 它应在该行之后引发异常:

Thread.sleep(2000);

But this my code is not throwing the exception. 但这不是我的代码抛出异常。

Please help what is missing. 请帮助缺少的内容。

Thanks in advance for any other suggested approach for the same purpose. 在此先感谢您为相同目的提出的其他建议方法。

For the approach you're using, it isn't sufficient to add @Timeable annotations, you also need to configure aspect weaving as described on Weaving Java Binaries . 对于您使用的方法,仅添加@Timeable注释还不够,还需要按照Weaving Java Binaries中的说明配置方面编织。

It's interesting to note that the blog post author and creator of jcabi-aspects , Yegor Bugayenko, has since decided that Java annotations are a big mistake . 有趣的是,此博客作者兼jcabi-aspects的创建者Yegor Bugayenko决定将Java批注视为一个大错误

Another approach is to use CompletableFuture : 另一种方法是使用CompletableFuture

public void testMethod() {
    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("Interrupted", e);
        }
    });
    try {
        future.get(1000, TimeUnit.MILLISECONDS);
    } catch (TimeoutException e) {
        // Operation timed out. Cancel it and log.
        future.cancel(true);
        logger.error("Timed out", e);
    } catch (InterruptedException e) {
        // Current thread interrupted while waiting. Cancel operation and log.
        future.cancel(true);
        logger.error("Interrupted", e);
        // Reassert interrupt flag, since exception is not propagated.
        Thread.currentThread().interrupt();
    } catch (ExecutionException e) {
        logger.error("Operation failed", e.getCause());
        // No need to cancel in this case, since the operation has completed.
    }
}

Note that the code always reasserts interrupt status when catching InterruptedException . 请注意,代码在捕获InterruptedException时始终会重新声明中断状态。 See Why invoke Thread.currentThread.interrupt() in a catch InterruptException block? 请参阅为什么在catch InterruptException块中调用Thread.currentThread.interrupt()?

Also note that the operation is explicitly cancelled if it times out or the calling thread is interrupted, to avoid wasting resources. 还要注意,如果操作超时或调用线程被中断,则该操作将被显式取消,以避免浪费资源。

As already mentioned in the comments, this solution seems to be usuable in your case as well. 正如评论中已经提到的, 此解决方案在您的情况下似乎也是可用的。 It would look like this: 它看起来像这样:

public void testMethod() {
    ForkJoinPool forkJoinPool = new ForkJoinPool(1);
    try {
        forkJoinPool.submit(() ->
        {
        // replace the following linea with the actual code that should be in this method
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {}
            System.out.println("Job done");
        })
        // wait for x milliseconds before wait times out and TimeOutException is thrown
                .get(1000, TimeUnit.MILLISECONDS);
    } catch (TimeoutException e) {
        // job not done in your interval
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    } 
}

Since the Thread#sleep takes 2 seconds, which is more than the 1 second wait time out specified in the .get(...) , this method will always time out in this example. 由于Thread#sleep花费2秒,这比.get(...)指定的1秒等待超时要长,因此在此示例中,此方法将始终超时。

Here is the code and its self explanatory: For testing purpose I have just written s simple method that will execute for only 3 seconds. 这是代码及其自我解释:为了测试目的,我只编写了一个仅执行3秒的简单方法。

import java.util.Timer;
import java.util.TimerTask;

class Test {

    Timer timer;

    public Test(int seconds) {
        timer = new Timer();
        timer.schedule(new RemindTask(), seconds * 1000);
    }

    class RemindTask extends TimerTask {
        public void run() {
            System.out.format("Time's up!%n");
            System.exit(0);
            timer.cancel();
        }
    }

    public static void main(String args[]) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                 new Test(3);
                 sum();
                 System.out.format("Task scheduled.%n");
            }
        });
       t.start();
    }

    public static void sum(){
        for(int i = 0 ; i < 100 ;i++){
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(i);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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