Mam program, który generuje wątki (~ 5-150), które wykonują kilka zadań. Początkowo użyłem a, FixedThreadPool
ponieważ to podobne pytanie sugerowało, że lepiej nadają się do dłuższych zadań, a przy mojej bardzo ograniczonej wiedzy na temat wielowątkowości, uznałem średni czas życia wątków (kilka minut) za „ długi czas ”.
Jednak ostatnio dodałem możliwość tworzenia dodatkowych wątków i dzięki temu przekraczam ustawiony przeze mnie limit wątków. Czy w takim przypadku lepiej byłoby zgadnąć i zwiększyć liczbę wątków, na które mogę zezwolić, czy przełączyć się na CachedThreadPool
tak, aby nie było zmarnowanych wątków?
Wypróbowując oba na wstępie, nie wydaje się, żeby było różnica, więc jestem skłonny iść z nimi CachedThreadPool
tylko po to, aby uniknąć marnotrawstwa. Jednak czy żywotność nici oznacza, że powinienem zamiast tego FixedThreadPool
wybrać i zająć się nieużywanymi wątkami? To pytanie sprawia, że wydaje się, że te dodatkowe wątki nie są zmarnowane, ale byłbym wdzięczny za wyjaśnienie.
ThreadPoolExecutor
podobnegoThreadPoolExecutor(0, maximumPoolSize, 60L, TimeUnit.SECONDS, SynchronousQueue())
?Jedno
FixedThreadPool
iCachedThreadPool
drugie jest złe w mocno obciążonych aplikacjach.CachedThreadPool
jest bardziej niebezpieczne niżFixedThreadPool
Jeśli Twoja aplikacja jest mocno obciążona i wymaga małych opóźnień, lepiej pozbyć się obu opcji ze względu na poniższe wady
CachedThreadPool
utratę kontroli podczas tworzenia wątkówPonieważ wiesz, że jedno i drugie jest złem, mniejsze zło nie przynosi żadnego dobra. Preferuj ThreadPoolExecutor , który zapewnia szczegółową kontrolę wielu parametrów.
beforeExecute(Thread, Runnable)
iafterExecute(Runnable, Throwable)
źródło
Czy na pewno rozumiesz, w jaki sposób wątki są faktycznie przetwarzane przez wybrany system operacyjny i sprzęt? Jak Java mapuje wątki na wątki systemu operacyjnego, jak mapuje wątki na wątki procesora itp.? Pytam, ponieważ tworzenie 150 wątków w JEDNYM JRE ma sens tylko wtedy, gdy masz pod spodem masywne rdzenie / wątki procesora, co najprawdopodobniej nie ma miejsca. W zależności od używanego systemu operacyjnego i pamięci RAM utworzenie więcej niż n wątków może nawet spowodować zamknięcie środowiska JRE z powodu błędów OOM. Więc naprawdę powinieneś odróżnić wątki i pracę do wykonania przez te wątki, ile pracy jesteś w stanie przetworzyć itp.
I to jest problem z CachedThreadPool: nie ma sensu umieszczać w kolejce długich prac w wątkach, które w rzeczywistości nie mogą działać, ponieważ masz tylko 2 rdzenie procesora zdolne do przetwarzania tych wątków. Jeśli skończysz z 150 zaplanowanymi wątkami, możesz stworzyć wiele niepotrzebnych narzutów dla harmonogramów używanych w Javie i systemie operacyjnym do ich jednoczesnego przetwarzania. Jest to po prostu niemożliwe, jeśli masz tylko 2 rdzenie procesora, chyba że twoje wątki przez cały czas czekają na operacje we / wy lub takie. Ale nawet w takim przypadku wiele wątków spowodowałoby wiele operacji we / wy ...
I ten problem nie występuje w przypadku FixedThreadPool, utworzonej z np. 2 + n wątków, gdzie n jest oczywiście rozsądnie niskie, ponieważ przy tym sprzęcie i zasobach systemu operacyjnego są używane ze znacznie mniejszym narzutem na zarządzanie wątkami, które i tak nie mogą działać.
źródło