我想创建一个可以运行方法的类,直到满足返回值的条件。
看起来应该是这样的
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 <T> MethodPoller method(Supplier<T> supplier) {
return this;
}
public <T> MethodPoller until(Predicate<T> predicate) {
return this;
}
}
但是我很难从这里开始 在满足条件之前,如何实现对常规方法的重试? 感谢。
答案 0 :(得分:21)
是的,这可以在Java 7中轻松完成,甚至可以使用Java 8完成。
method
方法的参数应为java.util.function.Supplier<T>
,until
方法的参数应为java.util.function.Predicate<T>
。
然后,您可以使用方法引用或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<T> {
Duration pollDurationSec;
int pollIntervalMillis;
private Supplier<T> pollMethod = null;
private Predicate<T> pollResultPredicate = null;
public MethodPoller() {
}
public MethodPoller<T> poll(Duration pollDurationSec, int pollIntervalMillis) {
this.pollDurationSec = pollDurationSec;
this.pollIntervalMillis = pollIntervalMillis;
return this;
}
public MethodPoller<T> method(Supplier<T> supplier) {
pollMethod = supplier;
return this;
}
public MethodPoller<T> until(Predicate<T> 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<String> poller = new MethodPoller<>();
String uuidThatStartsWithOneTwoThree = poller.method(() -> UUID.randomUUID().toString())
.until(s -> s.startsWith("123"))
.execute();
assertTrue(uuidThatStartsWithOneTwoThree.startsWith("123"));
System.out.println(uuidThatStartsWithOneTwoThree);
}
}
答案 1 :(得分:13)
您可以使用Awaitility吗?
而不是自己编写await()
.atMost(3, SECONDS)
.until(dog::bark, equalTo("woof"));
答案 2 :(得分:3)
您可以使用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/
答案 3 :(得分:3)
以下是使用Failsafe的解决方案:
RetryPolicy retryPolicy = new RetryPolicy()
.retryIf(bark -> bark.equals("Woof"))
.withMaxDuration(pollDurationSec, TimeUnit.SECONDS);
.withDelay(pollIntervalMillis, TimeUnit.MILLISECONDS);
Failsafe.with(retryPolicy).get(() -> dog.bark());
如您所见,非常简单,并处理您的确切情况。