Tworzenie wątków Java jest kosztowne, ponieważ wymaga sporo pracy:
- Duży stos pamięci musi zostać przydzielony i zainicjowany dla stosu wątków.
- Należy wykonać wywołania systemowe, aby utworzyć / zarejestrować natywny wątek w systemie operacyjnym hosta.
- Deskryptory muszą zostać utworzone, zainicjowane i dodane do wewnętrznych struktur danych JVM.
Jest to również kosztowne w tym sensie, że nić ogranicza zasoby, dopóki żyje; np. stos wątków, dowolne obiekty dostępne ze stosu, deskryptory wątków JVM, natywne deskryptory wątków systemu operacyjnego.
Koszty wszystkich tych rzeczy zależą od platformy, ale nie są tanie na żadnej platformie Java, z którą się kiedykolwiek spotkałem.
Wyszukiwarka Google znalazła mi stary test porównawczy, który zgłasza szybkość tworzenia wątków wynoszącą ~ 4000 na sekundę w Sun Java 1.4.1 na vintage'owym podwójnym procesorze Xeon z 2002 roku z Linuxem z 2002 roku. Bardziej nowoczesna platforma da lepsze liczby ... i nie mogę komentować metodologii ... ale przynajmniej daje szansę na określenie, jak drogie może być tworzenie wątków.
Testy porównawcze Petera Lawreya wskazują, że tworzenie wątków jest obecnie znacznie szybsze w wartościach bezwzględnych, ale nie jest jasne, ile z tego wynika z usprawnień w Javie i / lub systemie operacyjnym ... lub wyższych prędkości procesora. Ale jego liczby wciąż wskazują na ponad 150-krotną poprawę, jeśli używasz puli wątków w porównaniu do tworzenia / rozpoczynania nowego wątku za każdym razem. (I podkreśla, że to wszystko jest względne ...)
(Powyższe zakłada „wątki rodzime” zamiast „zielone wątki”, ale wszystkie współczesne maszyny JVM używają wątków rodzimych ze względów wydajnościowych. Zielone wątki są prawdopodobnie tańsze w tworzeniu, ale płacisz za to w innych obszarach).
Zrobiłem trochę kopania, aby zobaczyć, jak naprawdę przydzielany jest stos wątku Java. W przypadku OpenJDK 6 w systemie Linux stos wątków jest przydzielany przez wywołanie, pthread_create
które tworzy wątek macierzysty. (JVM nie przekazuje pthread_create
wstępnie przydzielonego stosu.)
Następnie w pthread_create
ramach stosu jest przydzielane przez wywołanie mmap
w następujący sposób:
mmap(0, attr.__stacksize,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
Zgodnie z man mmap
tym MAP_ANONYMOUS
flaga powoduje, że pamięć jest inicjowana do zera.
Tak więc, chociaż może nie być konieczne zerowanie nowych stosów wątków Java (zgodnie ze specyfikacją JVM), w praktyce (przynajmniej w przypadku OpenJDK 6 w systemie Linux) są zerowane.