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