Napotkałem dwukrotnie problem polegający na tym, że wątek producenta tworzy N elementów roboczych, przesyła je do ExecutorService
, a następnie musi poczekać, aż wszystkie N zostaną przetworzone.Elastyczne CountDownLatch?
Ostrzeżenia
- N nie jest znana z góry. Gdyby tak było, po prostu utworzyłbym
CountDownLatch
, a następnie miał wątek producentaawait()
, aż wszystkie prace zostały zakończone. - Używanie
CompletionService
jest niewłaściwe, ponieważ mimo, że mój wątek producent musi blokować (tzn wywołująctake()
) nie żaden sposób sygnalizowania, że wszystkie prace są kompletne, aby spowodować wątek producent przestanie czekać.
My obecne rozwiązanie preferowane jest użycie licznika całkowitą oraz przyrostu tym, gdy element pracy jest złożony i ubytek, gdy element roboczy jest przetwarzany. Po przejściu wszystkich zadań N mój wątek producenta będzie musiał poczekać na blokadę, sprawdzając, czy counter == 0
, gdy jest powiadomiony. Gwinty konsumenckie będą musiały powiadomić producenta, jeśli zmniejszyło licznik, a nowa wartość to 0.
Czy istnieje lepsze podejście do tego problemu lub czy istnieje odpowiednia konstrukcja w java.util.concurrent
Powinienem raczej użyć niż "toczyć własne"?
Z góry dziękuję.
W którym momencie producent wie, ile jest elementów roboczych? Kiedy ostatni element został wyprodukowany? –
Twoje obecne rozwiązanie może ucierpieć z powodu wyścigu: wyprodukuj przedmiot 1 -> counter ++ -> element procesu 1 -> counter-- -> wyprodukuj pozycję 2. Ponieważ licznik został zmniejszony, zanim producent wyprodukuje następny element, producent myśli, że jest gotowy. –
@rwwilden: Masz rację, że taki scenariusz może wystąpić. Jednak mój producent sprawdzał/czekał na liczniku po przesłaniu * wszystkich * elementów pracy, więc nie stanowi to stanu wyścigu w tym konkretnym przypadku. – Adamski