Czytałem tutaj JavaDoc dla Threadlocal
https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ThreadLocal.html
i mówi, że „wystąpienia ThreadLocal są zwykle prywatnymi polami statycznymi w klasach, które chcą powiązać stan z wątkiem (np. identyfikator użytkownika lub identyfikator transakcji)”.
Ale moje pytanie brzmi: dlaczego zdecydowali się uczynić go statycznym (zazwyczaj) - może to trochę zagmatwać stan „na wątek”, ale pola są statyczne?
źródło
ThreadLocal
do przechowywania odniesienia do zestawu skrótów, który mapuje obiekty na wystąpienia dla poszczególnych wątków.ThreadLocal
będzie przechowywać swoje własne dane lokalne wątku, nawet jeśli teThreadLocal
instancje istnieją w tym samym wątku. Niekoniecznie jest to złe - przypuszczam, że może to być najmniej popularny wzór z tych dwóchAlbo uczyń go statycznym, albo jeśli próbujesz uniknąć jakichkolwiek statycznych pól w swojej klasie - utwórz samą klasę jako singleton, a następnie możesz bezpiecznie używać poziomu wystąpienia ThreadLocal, o ile masz ten singleton dostępny globalnie.
źródło
Nie musi tak być. Ważne jest to, że powinien to być singleton.
źródło
Powodem jest to, że dostęp do zmiennych uzyskuje się poprzez wskaźnik powiązany z wątkiem. Działają jak zmienne globalne z zasięgiem wątku, dlatego statyczne jest najbliższym dopasowaniem. W ten sposób uzyskujesz stan lokalny wątku w rzeczach takich jak pthreads, więc może to być po prostu przypadek historii i implementacji.
źródło
Zastosowanie Threadlocal na instancji na wątek polega na tym, że chcesz, aby coś było widoczne we wszystkich metodach obiektu i aby było bezpieczne wątkowo bez synchronizowania dostępu do niego, tak jak w przypadku zwykłego pola.
źródło
Odnieś się do tego , aby uzyskać lepsze zrozumienie.
Krótko mówiąc,
ThreadLocal
obiekt działa jak mapa klucz-wartość. KiedyThreadLocal
get/set
metoda wywołania wątku pobierze / zapisze obiekt wątku w kluczu mapy, a wartość w wartości mapy. Dlatego różne wątki mają różne skopiowane wartości (które chcesz przechowywać lokalnie), ponieważ znajdują się one we wpisach różnych map.Dlatego potrzebujesz tylko jednej mapy, aby zachować wszystkie wartości. Chociaż nie jest to konieczne, możesz mieć wiele map (bez deklarowania statycznego), aby zachować również każdy obiekt wątku, co jest całkowicie redundantne, dlatego preferowana jest zmienna statyczna.
źródło
static final ThreadLocal
zmienne są bezpieczne dla wątków.static
sprawia, że zmienna ThreadLocal jest dostępna w wielu klasach tylko dla odpowiedniego wątku. jest to rodzaj deklaracji zmiennych globalnych odpowiednich zmiennych lokalnych wątku w wielu klasach.Możemy sprawdzić bezpieczeństwo tego wątku za pomocą następującego przykładu kodu.
CurrentUser
- przechowuje bieżący identyfikator użytkownika w ThreadLocalTestService
- Prosta usługa z metodą -getUser()
aby pobrać bieżącego użytkownika z CurrentUser.TestThread
- ta klasa służy do tworzenia wielu wątków i jednoczesnego ustawiania identyfikatorów użytkowników.
.
.
Uruchom główną klasę TestThread. Wynik -
Podsumowanie analizy
main
wykonanie kończy się i wyświetla aktualnego użytkownika jako "62", równolegleForkJoinPool.commonPool-worker-1
wykonywanie kończy się i wyświetla bieżącego użytkownika jako "87", równolegleForkJoinPool.commonPool-worker-2
kończy się wykonywanie i wyświetla aktualnego użytkownika jako "31", równolegleForkJoinPool.commonPool-worker-3
wykonywanie kończy się i wyświetla aktualnego użytkownika jako "81"Wnioskowanie
Współbieżne wątki mogą pobierać poprawne identyfikatory użytkowników, nawet jeśli zostały zadeklarowane jako „statyczne końcowe ThreadLocal”
źródło