限制java中方法的执行时间

时间:2017-08-17 08:09:28

标签: java

我想限制java中方法的执行时间,我希望我的特定方法如果在某个特定的时间内执行它,那么确定它应该抛出异常。

为此,我尝试使用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());
        }
}

为此,我参考了: http://www.yegor256.com/2014/06/20/limit-method-execution-time.html

它应该在行之后抛出异常:

Thread.sleep(2000);

但是我的代码并没有抛出异常。

请帮助缺少。

提前感谢任何其他建议用于同一目的的方法。

3 个答案:

答案 0 :(得分:3)

对于您正在使用的方法,仅添加@Timeable注释是不够的,您还需要按Weaving Java Binaries中所述配置方面编织。

值得注意的是,jcabi-aspects的帖子作者和创作者Yegor Bugayenko已经决定Java annotations are a big mistake

另一种方法是使用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.
    }
}

请注意,代码在捕获InterruptedException时始终会重新确认中断状态。见Why invoke Thread.currentThread.interrupt() in a catch InterruptException block?

另请注意,如果超时或调用线程被中断,操作将被明确取消,以避免浪费资源。

答案 1 :(得分:2)

正如评论中已经提到的,this solution似乎也适用于您的情况。它看起来像这样:

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

由于Thread#sleep需要2秒,这超过.get(...)中指定的1秒等待时间,因此此方法在此示例中将始终超时。

答案 2 :(得分:0)

这是代码及其自我解释:出于测试目的,我刚刚编写了一个只执行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);
        }
    }
}