Java 8 – 重试方法,直到满足条件(间隔)

我想创建一个可以运行方法的类,直到满足返回值的条件。

看起来应该是这样的

methodPoller.poll(pollDurationSec, pollIntervalMillis) .method(dog.bark()) .until(dog -> dog.bark().equals("Woof")) .execute(); 

我的方法poller看起来有点像这个()//跟随GuiSim回答

 public class MethodPoller { Duration pollDurationSec; int pollIntervalMillis; public MethodPoller() { } public MethodPoller poll(Duration pollDurationSec, int pollIntervalMillis) { this.pollDurationSec = pollDurationSec; this.pollIntervalMillis = pollIntervalMillis; return this; } public  MethodPoller method(Supplier supplier) { return this; } public  MethodPoller until(Predicate predicate) { return this; } } 

但是我很难从这里开始。
在满足条件之前,如何实现对常规方法的重试?
谢谢。

是的,这可以在Java 7中轻松完成,甚至可以使用Java 8完成。

method方法的参数应该是java.util.function.Supplier ,而until方法的参数应该是java.util.function.Predicate

然后,您可以使用方法引用或lambda表达式来创建Poller,如下所示:

 myMethodPoller.poll(pollDurationInteger, intervalInMillisecond) .method(payment::getStatus) .until (paymentStatus -> paymentStatus.getValue().equals("COMPLETED")) .execute(); 

作为旁注,如果您打算使用Java 8,我建议使用java.time.Duration而不是整数来表示轮询持续时间和间隔。

我还建议您查看https://github.com/rholder/guava-retrying ,这是一个您可以使用的库。 如果没有,它可能是您API的一个很好的灵感,因为它具有漂亮的流畅API。

编辑:在更新问题之后,这是一个简单的实现。 我已经留下了一些部分供你完成TODO。

 import java.time.Duration; import java.util.function.Predicate; import java.util.function.Supplier; public class MethodPoller { Duration pollDurationSec; int pollIntervalMillis; private Supplier pollMethod = null; private Predicate pollResultPredicate = null; public MethodPoller() { } public MethodPoller poll(Duration pollDurationSec, int pollIntervalMillis) { this.pollDurationSec = pollDurationSec; this.pollIntervalMillis = pollIntervalMillis; return this; } public MethodPoller method(Supplier supplier) { pollMethod = supplier; return this; } public MethodPoller until(Predicate predicate) { pollResultPredicate = predicate; return this; } public T execute() { // TODO: Validate that poll, method and until have been called. T result = null; boolean pollSucceeded = false; // TODO: Add check on poll duration // TODO: Use poll interval while (!pollSucceeded) { result = pollMethod.get(); pollSucceeded = pollResultPredicate.test(result); } return result; } } 

样品用途:

 import static org.junit.Assert.assertTrue; import java.util.UUID; import org.junit.Test; public class MethodPollerTest { @Test public void test() { MethodPoller poller = new MethodPoller<>(); String uuidThatStartsWithOneTwoThree = poller.method(() -> UUID.randomUUID().toString()) .until(s -> s.startsWith("123")) .execute(); assertTrue(uuidThatStartsWithOneTwoThree.startsWith("123")); System.out.println(uuidThatStartsWithOneTwoThree); } } 

你可以使用Awaitility而不是自己写这个吗?

 await() .atMost(3, SECONDS) .until(dog::bark, equalTo("woof")); 

您可以使用RxJava

  Observable.interval(3, TimeUnit.SECONDS, Schedulers.io()) .map(tick -> dog) .takeWhile( dog-> { return ! dog.bark().equals("Woof"); }) .subscribe(dog ->dog.bark()); try { Thread.sleep(10000); }catch(Exception e){} 

http://blog.freeside.co/2015/01/29/simple-background-polling-with-rxjava/

这是使用Failsafe的解决方案:

 RetryPolicy retryPolicy = new RetryPolicy() .retryIf(bark -> bark.equals("Woof")) .withMaxDuration(pollDurationSec, TimeUnit.SECONDS); .withDelay(pollIntervalMillis, TimeUnit.MILLISECONDS); Failsafe.with(retryPolicy).get(() -> dog.bark()); 

你可以看到非常简单,并处理你的确切场景。