Jaka dokładnie jest różnica między wielkością puli podstawowej a maksymalnym rozmiarem puli, gdy mówimy o ThreadPoolExecutor
?
Czy można to wyjaśnić na przykładzie?
java
asynchronous
threadpoolexecutor
user2568266
źródło
źródło
Odpowiedzi:
Z tego wpisu na blogu :
źródło
allowCoreThreadTimeOut(boolean)
która pozwala na zabijanie głównych wątków po określonym czasie bezczynności. Ustawienie wartości true i ustawieniecore threads
=max threads
umożliwia skalowanie puli wątków od 0 domax threads
.JEŚLI uruchomione wątki> corePoolSize & <maxPoolSize , a następnie utwórz nowy wątek, jeśli kolejka zadań Total jest pełna i nadchodzi nowy.
Form doc: (Jeśli jest więcej niż corePoolSize, ale mniej niż maximumPoolSize uruchomionych wątków, nowy wątek zostanie utworzony tylko wtedy, gdy kolejka jest pełna.)
Weźmy teraz prosty przykład:
Tutaj 5 to corePoolSize - oznacza, że Jvm utworzy nowy wątek dla nowego zadania dla pierwszych 5 zadań. a inne zadania będą dodawane do kolejki aż do zapełnienia kolejki (50 zadań).
10 to maxPoolSize - JVM może utworzyć maksymalnie 10 wątków. Oznacza, że jeśli jest już uruchomionych 5 zadań / wątków, a kolejka jest pełna z 50 oczekującymi zadaniami i jeśli w kolejce pojawi się jeszcze jedno nowe żądanie / zadanie, JVM utworzy nowy wątek do 10 (łącznie wątków = poprzednie 5 + nowe 5) ;
new ArrayBlockingQueue (50) = to całkowity rozmiar kolejki - może w niej umieścić 50 zadań.
gdy wszystkie 10 wątków są uruchomione i nadejdzie nowe zadanie, to nowe zadanie zostanie odrzucone.
Zasady tworzenia wątków wewnętrznie przez SUN:
Jeśli liczba wątków jest mniejsza niż corePoolSize, utwórz nowy wątek, aby uruchomić nowe zadanie.
Jeśli liczba wątków jest równa (lub większa) niż corePoolSize, umieść zadanie w kolejce.
Jeśli kolejka jest pełna, a liczba wątków jest mniejsza niż maxPoolSize, utwórz nowy wątek do uruchamiania zadań.
Jeśli kolejka jest pełna, a liczba wątków jest większa lub równa maxPoolSize, odrzuć zadanie.
Mam nadzieję, że to jest HelpFul ... i proszę mnie poprawić, jeśli się mylę ...
źródło
Z dokumentu :
Ponadto:
źródło
Jeśli zdecydujesz się utworzyć
ThreadPoolExecutor
ręcznie zamiast używaćExecutors
klasy fabrycznej, będziesz musiał utworzyć i skonfigurować klasę za pomocą jednego z jej konstruktorów. Najbardziej rozbudowanym konstruktorem tej klasy jest:Jak widać, możesz skonfigurować:
Ograniczanie liczby zadań w kolejce
Ograniczenie liczby wykonywanych współbieżnych zadań, zmiana rozmiaru puli wątków, stanowi ogromną korzyść dla aplikacji i jej środowiska wykonawczego pod względem przewidywalności i stabilności: nieograniczone tworzenie wątków ostatecznie wyczerpuje zasoby środowiska wykonawczego, a w konsekwencji może wystąpić sytuacja dla aplikacji , poważne problemy z wydajnością, które mogą prowadzić nawet do niestabilności aplikacji.
To rozwiązanie tylko jednej części problemu: ograniczasz liczbę wykonywanych zadań, ale nie ograniczasz liczby zadań, które można przesłać i umieścić w kolejce do późniejszego wykonania. Aplikacja doświadczy później niedoboru zasobów, ale w końcu to odczuje, jeśli wskaźnik zgłoszeń będzie stale przekraczał wskaźnik wykonania.
Rozwiązanie tego problemu jest następujące: Zapewnienie kolejki blokującej do executora w celu wstrzymania oczekujących zadań. W przypadku zapełnienia się kolejki przesłane zadanie zostanie „odrzucone”.
RejectedExecutionHandler
Jest wywoływana gdy złożenie zadanie zostanie odrzucony, i dlatego został odrzucony czasownik cytowane w poprzednim punkcie. Możesz wdrożyć własną politykę odrzucania lub użyć jednej z wbudowanych zasad udostępnionych przez platformę.Domyślne zasady odrzucania powodują, że moduł wykonawczy zgłasza plik
RejectedExecutionException
. Jednak inne wbudowane zasady pozwalają:źródło
Źródło
Zasady dotyczące rozmiaru
ThreadPoolExecutor's
puli są generalnie niezrozumiałe, ponieważ nie działają one tak, jak myślisz, że powinny lub w sposób, w jaki chcesz.Weźmy ten przykład. Początkowy rozmiar puli wątków to 1, rozmiar puli podstawowej to 5, maksymalny rozmiar puli to 10, a kolejka to 100.
Na sposób firmy Sun: gdy żądania przychodzą w wątkach, zostanie utworzonych do 5, następnie zadania będą dodawane do kolejki, aż osiągnie 100. Gdy kolejka będzie pełna, zostaną utworzone nowe wątki do
maxPoolSize
. Gdy wszystkie wątki będą używane, a kolejka jest pełna, zadania zostaną odrzucone. Wraz ze zmniejszaniem się kolejki zmniejsza się liczba aktywnych wątków.Sposób przewidywany przez użytkownika: gdy żądania przychodzą w wątkach, zostanie utworzonych do 10, następnie zadania będą dodawane do kolejki, aż osiągnie 100, po czym zostaną odrzucone. Liczba wątków zmieni się na maksymalną, aż kolejka będzie pusta. Kiedy kolejka jest pusta, wątki będą ginąć, dopóki nie zostaną
corePoolSize
.Różnica polega na tym, że użytkownicy chcą zacząć zwiększać rozmiar puli wcześniej i chcą, aby kolejka była mniejsza, podczas gdy metoda Sun chce utrzymać mały rozmiar puli i zwiększyć go tylko wtedy, gdy obciążenie stanie się zbyt duże.
Oto proste zasady Sun dotyczące tworzenia wątków:
corePoolSize
, utwórz nowy wątek, aby uruchomić nowe zadanie.corePoolSize
, umieść zadanie w kolejce.maxPoolSize
, utwórz nowy wątek do uruchamiania zadań.maxPoolSize
, odrzuć zadanie. Krótko mówiąc, nowe wątki są tworzone tylko wtedy, gdy kolejka się zapełnia, więc jeśli używasz kolejki nieograniczonej, liczba wątków nie przekroczycorePoolSize
.Aby uzyskać pełniejsze wyjaśnienie, pobierz to z paszczy konia:
ThreadPoolExecutor
dokumentacja API.Jest naprawdę dobry post na forum, który przedstawia sposób, w jaki
ThreadPoolExecutor
działa z przykładami kodu: http://forums.sun.com/thread.jspa?threadID=5401400&tstart=0Więcej informacji: http://forums.sun.com/thread.jspa?threadID=5224557&tstart=450
źródło
Definicję terminów corepoolsize i maxpoolsize można znaleźć w pliku javadoc. http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html
Powyższy link zawiera odpowiedź na Twoje pytanie. Jednak tylko po to, aby było jasne. Aplikacja będzie kontynuować tworzenie wątków, aż osiągnie corePoolSize. Myślę, że chodzi tutaj o to, aby tych wiele wątków wystarczyło do obsługi napływu zadań. Jeśli nowe zadanie pojawi się po utworzeniu wątków corePoolSize, zadania zostaną umieszczone w kolejce. Gdy kolejka będzie pełna, executor rozpocznie tworzenie nowych wątków. To rodzaj równoważenia. Zasadniczo oznacza to, że napływ zadań jest czymś więcej niż możliwościami przetwarzania. Zatem Executor zacznie ponownie tworzyć nowe wątki, aż osiągnie maksymalną liczbę wątków. Ponownie, nowe wątki zostaną utworzone wtedy i tylko wtedy, gdy kolejka jest pełna.
źródło
Dobre wyjaśnienie na tym blogu:
Ilustracja
Wynik :
źródło
Z książki Java concurency essentials :
CorePoolSize : ThreadPoolExecutor ma atrybut corePoolSize, który określa, ile wątków rozpocznie, dopóki nowe wątki nie zostaną uruchomione, gdy kolejka jest pełna
MaximumPoolSize : Ten atrybut określa, jak wiele wątków są uruchomione na maksimum. Możesz ustawić to na Integer. MAX_VALUE, aby nie mieć górnej granicy
źródło
java.util.concurrent.ThreadPoolExecutor
źródło
Zrozumienie wewnętrznego zachowania
ThreadPoolExecutor
po przesłaniu nowego zadania pomogło mi zrozumieć,corePoolSize
czym sięmaximumPoolSize
różnią.Pozwolić:
N
być liczba wątków w baseniegetPoolSize()
. Aktywne wątki + nieaktywne wątki.T
być liczbą zadań przekazanych wykonawcy / puli.C
być podstawą wielkości basen,getCorePoolSize()
. Ile maksymalnie wątków można utworzyć na pulę dla zadań przychodzących, zanim nowe zadania trafią do kolejki .M
być maksymalna wielkość basenu,getMaximumPoolSize()
. Maksymalna liczba wątków, które może przydzielić pula.Zachowania
ThreadPoolExecutor
w Javie po przesłaniu nowego zadania:N <= C
przypadku bezczynnych wątków nie jest przypisywane nowe zadanie przychodzące, zamiast tego tworzony jest nowy wątek.N > C
i jeśli są bezczynne wątki, to jest tam przypisywane nowe zadanie.N > C
i jeśli NIE ma bezczynnych wątków, nowe zadania są umieszczane w kolejce. NIE STWORZONO TUTAJ NOWYCH NITKÓW.M
. JeśliM
zostanie osiągnięty, odrzucamy zadania. Ważne, aby tego nie było, to fakt, że nie tworzymy nowych wątków, dopóki kolejka nie będzie pełna!Źródła:
Przykłady
Przykład z
corePoolSize = 0
imaximumPoolSize = 10
z pojemnością kolejki50
.Spowoduje to powstanie jednego aktywnego wątku w puli, dopóki kolejka nie będzie zawierała 50 elementów.
Przykład z
corePoolSize = 10
imaximumPoolSize = 10
z pojemnością kolejki50
.Spowoduje to utworzenie 10 aktywnych wątków w puli. Gdy kolejka zawiera 50 pozycji, zadania zostaną odrzucone.
źródło