Sekwencyjne wywołanie CompletableFuture

0

WItam,

mam taką zagwozdkę.
Uruchamiam sekwencyjnie listę CompletableFuture jeden po drugim aż do momentu gdy pierwszy zwróci pożądany wynik. Ponieważ nie wiem ile tych iteracji będzie opakowuje wszystko w pętlę while(shouldKeepReading) i gdy dostanę odpowiedni wynik z future przerywam pętlę. Zmienna shouldKeepReading jest volatile aby zachować relacje happens-before. Wydaje się wszystko powinno działać ale jednak pętla nie zatrzymuje się po pierwszym spełnionym warunku. Zazwyczaj wykonuje jeszcze następny, tak jakby kolejna egzekucja nie widziała zmienionej flagi wyjścia z pętli. Trochę mnie to dziwi ponieważ mamy relacje write-read, czyli żaden kolejny odczyt nie powinien widzieć starej wartości jeśli wcześniej nastąpiła zmiana warunku.

Ktoś może wie dlaczego to nie działa i czego tu brakuje?

volatile boolean shouldKeepReading = true;
....
List<Supplier<CompletableFuture<Integer>>> listOfPromises;
        
      while (shouldKeepReading) {
       listOfPromises.getNext().get().thenApply(result -> {
          if (conditionPass(result)) {
            shouldKeepReading = false;
          }
          return res;
        });
    }

Pozdrawiam
Maciej

2

Na jakiej puli wątków te futury są odpalane? Wyjście z pętli (w wątku main) nie spowoduje wstrzymania pracy pozostałych wątków.

0

Mógłbyś pokazać jak wygląda przykładowy element listy listOfPromises? Bo jak w stylu CompletableFuture#supplyAsync, to thenApply się wykona w innym wątku.

0

Zmieniłem kod tak aby promisy uruchamiały się sekwencyjnie, dodatkowo dodałem double checking przez wywołaniem kolejnego elementu, wydaje się że teraz działa, co ciekawe trochę dziwne, że teraz volatile nie ma znaczenia, bez tego również działa poprawnie,

volatile boolean shouldKeepReading = true;
....
CompletableFuture<Integer> result = promissesQueue.poll().get();

while (shouldKeepReading) {
      result = result.thenCompose(res -> {
        if (conditionPass(res)) {
          shouldKeepReading = false;
          return CompletableFuture.completedFuture(0));
        } else {
          if (shouldKeepReading) {
            return promissesQueue.poll().get();
          } else {
            return CompletableFuture.completedFuture(0));
          }
        }
      });
0

Trochę dziwny jest ten kod, chociażby z tego względu, że w pewnym momencie kolejka może być pusta i wtedy to się wywali.

1 użytkowników online, w tym zalogowanych: 0, gości: 1