Java重复执行任务-直到超时发生或条件满足-同步执行
我目前面临一个具体的问题,我不知道如何解决它。让我 请简要描述此问题:Java重复执行任务-直到超时发生或条件满足-同步执行,java,scheduled-tasks,Java,Scheduled Tasks,我目前面临一个具体的问题,我不知道如何解决它。让我 请简要描述此问题: 在一个方法中,我必须调用另一个方法并处理其响应 如果这个响应等于某个值,我将继续常规执行 否则,我将等待x秒(例如2秒),然后再次调用该方法以再次处理其响应 重复最后一步,直到某个时间段到期,或者该方法交付预期响应。 因此,总的来说,我不会永远等待,而只会在最长10秒时等待,以查看该方法是否在该时间内返回预期响应 时间 备注:如果该方法不需要10秒来交付预期结果,则常规 之后应立即继续执行。这意味着我不想等10秒钟 如果结
- 在一个方法中,我必须调用另一个方法并处理其响应
- 如果这个响应等于某个值,我将继续常规执行
- 否则,我将等待x秒(例如2秒),然后再次调用该方法以再次处理其响应
- 重复最后一步,直到某个时间段到期,或者该方法交付预期响应。 因此,总的来说,我不会永远等待,而只会在最长10秒时等待,以查看该方法是否在该时间内返回预期响应 时间
- 备注:如果该方法不需要10秒来交付预期结果,则常规 之后应立即继续执行。这意味着我不想等10秒钟 如果结果在2秒钟后出现
//无异常处理以简化方法
public ComplexValuePart main方法(int-id){
//之前执行的其他代码
int最大数量=5;
int waitTime=2000;
int计数器=0;
布尔条件满足=假;
ComplexValue cv=null;
while(计数器+++
然而,使用Java8(这是我目前的限制)我认为可能有其他/更好的解决方案
作为替代方案,我使用ScheduledExecutorService提出了一些建议,例如:
public void mainMethod(int id) {
//Other code executed before
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
Future<?> future = service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
ComplexValue cv = calculatingMethod(id);
if (cv.conditionHolds()) {
//shutdown service including awaitTermination
}
}
}, 0, 2, TimeUnit.SECONDS);
try {
future.get(20, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
//shutdown service including awaitTermination
}
//Continue processing with cv - How can I access cv here?
}
public void main方法(int-id){
//之前执行的其他代码
ScheduledExecutorService服务=Executors.newScheduledThreadPool(1);
Future=service.scheduleAtFixedRate(新的Runnable(){
@凌驾
公开募捐{
ComplexValue cv=计算方法(id);
if(cv.conditionHolds()){
//关闭服务,包括终止
}
}
},0,2,时间单位为秒);
试一试{
future.get(20,时间单位:秒);
}捕获(InterruptedException | ExecutionException | TimeoutException e){
//关闭服务,包括终止
}
//继续处理cv-如何在此处访问cv?
}
要返回ComplexValue
我想我需要使用Callable
而不是Runnable
?我是否可以使用可调用的相应地执行此操作?
此外,即使服务执行中的条件在之前是正常的,它也总是会进入超时。
在这种情况下,我不知道对于实现如此简单的任务来说,这一切是否有点太“开销”。
与普通的线程睡眠相比,这种解决方案有什么好处
在实现这一部分时,我是否缺少一些Java8功能
注意:我不必在这个循环中并行执行不同的任务。主方法的执行不得继续
直到超时过期或达到所需的结果-因此,不会执行async
。
适当的方法需要根据服务调用的响应返回一些数据。我将使用TimerTask。它每隔“waitTime”毫秒重复执行“run”方法。您可以通过调用“timer.cancel()”指定何时停止重复此任务
此代码将继续调用doSomething()
,直到返回预期值或超过TIMEOUT\u MS
毫秒。假设doSomething()
返回速度很快,则所需时间不会超过TIMEOUT\u MS
(再加上几毫秒)。此外,重试间延迟是恒定的,与doSomething()
的运行时间无关(即使doSomething()
运行1.9秒,也将每2秒重试一次),最坏情况下所需的时间是TIMEOUT\u MS
+一次调用doSomething()
所需的时间
在自己的类timeout
中实现等待/超时逻辑可能是有益的。然后,您可以为给定的超时时间创建一个实例,并将其传递到不同的层,以便即使是最底层(例如网络IO)也可以适当地设置其超时值,使其不超过应用程序逻辑顶层定义的截止日期
将Timeout
类与多态RetryStrategies
相结合,您可以非常灵活地指定和处理许多不同的场景
使用lambdas,您甚至可以创建完整重试逻辑的完全通用封装,如
<R> R retryForResult( Supplier<R> functionToCall, Function<R,Boolean> resultValidationFunction, long maxTimeMs, Iterable<Long> retryDelays );
R retryForResult(供应商函数调用、函数结果验证函数、长maxTimeMs、Iterable retryDelays);
感谢您的建议。但在这种情况下,遵循timer.schedule…的代码将继续,而不等待计时器。因此,在这种情况下,我需要额外的措施,以确保该部分只持续到超时过期或条件得到满足,对吗?此外,通常不应该使用ScheduledExecutorService而不是计时器吗?满足条件后要执行的代码应该在if语句中(第10行my code)。ScheduledExecutorService与Timer相比有一些优势,但使用Timer,您可以获得更干净的代码,并且在不使用多线程时,在性能方面没有太大差异
public void mainMethod(int id) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
int counter = 0;
@Override
public void run() {
cv = calculatingMethod(id);
if (cv.conditionHolds() || counter++ > countLimit) {
// conditionFulfilled = true;
timer.cancel();
}
}
}, 0, waitTime);
}
final long deadline = System.currentTimeMillis() + TIMEOUT_MS;
boolean done;
Result result;
do {
result = doSomething();
done = resultIsOk(result);
if ( !done ) {
final long msRemaining = deadline - System.currentTimeMillis();
if ( msRemaining > 0 ) {
Thread.sleep(Math.min(msRemaining, RETRY_WAIT_TIME_MS);
} else {
done = true;
}
}
} while (!done);
if ( !resultIsOk(result) ) {
// Error or something.
}
<R> R retryForResult( Supplier<R> functionToCall, Function<R,Boolean> resultValidationFunction, long maxTimeMs, Iterable<Long> retryDelays );