Java 8 - 重试方法直到满足条件(按时间间隔)
Java 8 - retry a method until a condition is fulfilled (in intervals)
我想创建一个 class 可以 运行 的方法,直到满足有关 return 值的条件。
它应该看起来像这样
methodPoller.poll(pollDurationSec, pollIntervalMillis)
.method(dog.bark())
.until(dog -> dog.bark().equals("Woof"))
.execute();
我的方法轮询器看起来有点像这样 () // 按照 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;
}
}
但我很难从这里开始选择。
如何在满足条件之前重试通用方法?
谢谢
是的,这可以在 Java 7 中轻松完成,使用 Java 8 甚至更干净。
method
方法的参数应为 java.util.function.Supplier<T>
,until
方法的参数应为 java.util.function.Predicate<T>
。
然后您可以使用方法引用或 lambda 表达式来创建轮询器,如下所示:
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);
}
}
您可以使用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/
您可以使用 Awaitility 而不是自己编写吗?
await()
.atMost(3, SECONDS)
.until(dog::bark, equalTo("woof"));
这是一个使用 Failsafe 的解决方案:
RetryPolicy<String> retryPolicy = new RetryPolicy<String>()
.handleIf(bark -> bark.equals("Woof"))
.withMaxDuration(pollDurationSec, TimeUnit.SECONDS);
.withDelay(pollIntervalMillis, TimeUnit.MILLISECONDS);
Failsafe.with(retryPolicy).get(() -> dog.bark());
如您所见,非常简单明了,可以处理您的具体情况。
我想创建一个 class 可以 运行 的方法,直到满足有关 return 值的条件。
它应该看起来像这样
methodPoller.poll(pollDurationSec, pollIntervalMillis)
.method(dog.bark())
.until(dog -> dog.bark().equals("Woof"))
.execute();
我的方法轮询器看起来有点像这样 () // 按照 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;
}
}
但我很难从这里开始选择。
如何在满足条件之前重试通用方法?
谢谢
是的,这可以在 Java 7 中轻松完成,使用 Java 8 甚至更干净。
method
方法的参数应为 java.util.function.Supplier<T>
,until
方法的参数应为 java.util.function.Predicate<T>
。
然后您可以使用方法引用或 lambda 表达式来创建轮询器,如下所示:
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);
}
}
您可以使用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/
您可以使用 Awaitility 而不是自己编写吗?
await()
.atMost(3, SECONDS)
.until(dog::bark, equalTo("woof"));
这是一个使用 Failsafe 的解决方案:
RetryPolicy<String> retryPolicy = new RetryPolicy<String>()
.handleIf(bark -> bark.equals("Woof"))
.withMaxDuration(pollDurationSec, TimeUnit.SECONDS);
.withDelay(pollIntervalMillis, TimeUnit.MILLISECONDS);
Failsafe.with(retryPolicy).get(() -> dog.bark());
如您所见,非常简单明了,可以处理您的具体情况。