以限制 Java 中方法的执行时间

  • 本文关键字:方法 执行时间 Java java
  • 更新时间 :
  • 英文 :


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

为此,我尝试使用 :

@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);

但是我的代码并没有引发异常。

请帮助缺少的东西。

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

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

有趣的是,博客文章作者和jcabi-aspects的创建者Yegor Bugayenko已经决定Java注解是一个很大的错误。

另一种方法是使用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时始终重新断言中断状态。请参阅为什么在 catch InterruptException 块中调用 Thread.currentThread.interrupt((?

另请注意,如果操作超时或调用线程中断,则会显式取消该操作,以避免浪费资源。

正如评论中已经提到的,此解决方案似乎也可以在您的情况下使用。它看起来像这样:

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 秒等待超时多,因此此方法在本例中将始终超时。

以下是代码及其不言自明: 出于测试目的,我刚刚编写了一个简单的方法,该方法将仅执行 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);
}
}
}

最新更新