我想限制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);
但是我的代码并没有抛出异常。
请帮助缺少。
提前感谢任何其他建议用于同一目的的方法。
答案 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);
}
}
}