Es ist nicht bekannt, wenn die externen Daten zunächst verfügbar sind. Deshalb gibt GetCurrentData eine Zukunft zurück.
Code: Select all
@Slf4j
public class ScheduledProvider {
private static final Random RANDOM = new Random();
private final List futures = new ArrayList();
private final AtomicReference currentData = new AtomicReference();
public ScheduledProvider() {
final NamedThreadFactory namedThreadFactory = new NamedThreadFactory("scheduled-provider", (t, e) -> log.warn("Caught exception", e));
final ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(namedThreadFactory);
scheduledExecutor.scheduleAtFixedRate(this::tick, 1, 1, TimeUnit.SECONDS); // Simulate not initially available data by setting the initialdelay to 1 second
}
/** Prevent an exception to stop the scheduler */
private void tick() {
try {
updateData();
} catch (final Throwable t) {
log.warn("Swallow throwable", t);
}
}
private void updateData() {
final List list = List.of(getRandomIntBetween1And10(), getRandomIntBetween1And10(), getRandomIntBetween1And10());
log.info("Calculated new list={}", list);
final GatheredData newData = new GatheredData(list);
currentData.set(newData);
synchronized (futures) {
futures.forEach(future -> future.complete(newData));
futures.clear();
}
}
private int getRandomIntBetween1And10() {
return RANDOM.nextInt(10) + 1;
}
public CompletableFuture getCurrentData() {
final GatheredData data = currentData.get();
if (data != null) {
return CompletableFuture.completedFuture(data);
}
log.info("Data is loading...");
final CompletableFuture future = new CompletableFuture();
synchronized (futures) {
futures.add(future);
}
return future;
}
}