Sekwencyjne wywołanie CompletableFuture

Sekwencyjne wywołanie CompletableFuture
PM
  • Rejestracja:prawie 8 lat
  • Ostatnio:8 miesięcy
  • Postów:30
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?

Kopiuj
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

Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:około 9 godzin
  • Postów:1875
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.


”Engineering is easy. People are hard.” Bill Coughran
PM
nie tworzę puli wątków więc pewnie w głównym wątku, ale wątki powinny być uruchamiane sekwencyjnie tu, nie wszystkie na raz, chyba że się mylę
crejk
  • Rejestracja:ponad 6 lat
  • Ostatnio:2 dni
  • Postów:46
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.

edytowany 2x, ostatnio: crejk
PM
tak, supplyAsync, ok teraz widzę gdzie jest problem
PM
  • Rejestracja:prawie 8 lat
  • Ostatnio:8 miesięcy
  • Postów:30
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,

Kopiuj
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));
          }
        }
      });
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:około 9 godzin
  • Postów:1875
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.


”Engineering is easy. People are hard.” Bill Coughran

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.