Kiedy i jak należy używać zmiennej ThreadLocal?

Kiedy należy użyć zmiennej ThreadLocal?

Jak się go stosuje?

Author: Andrew Tobilko, 2009-05-03

22 answers

Jednym z możliwych (i powszechnych) zastosowań jest, gdy masz jakiś obiekt, który nie jest bezpieczny dla wątków, ale chcesz uniknąć synchronizacji dostępu do tego obiektu (patrzę na ciebie, SimpleDateFormat). Zamiast tego nadaj każdemu wątkowi własną instancję obiektu.

Na przykład:

public class Foo
{
    // SimpleDateFormat is not thread-safe, so give one to each thread
    private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue()
        {
            return new SimpleDateFormat("yyyyMMdd HHmm");
        }
    };

    public String formatIt(Date date)
    {
        return formatter.get().format(date);
    }
}

Dokumentacja .

 786
Author: overthink,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-25 17:51:39

Ponieważ {[0] } jest odniesieniem do danych w danym Thread, możesz skończyć z wyciekami klas podczas używania ThreadLocal s W serwerach aplikacji, które używają puli wątków. Musisz być bardzo ostrożny w czyszczeniu wszelkich ThreadLocals Ty get() lub set() za pomocą metody ThreadLocal s remove().

Jeśli nie posprzątać, gdy skończysz, wszelkie odniesienia posiada do klas załadowanych jako część wdrożonej webapp pozostanie w stałe sterty i nigdy nie dostanie śmieci zbierane. Redeploying / undeploying webapp nie wyczyści każdego Thread's odniesienie do klasy(es) webapp, ponieważ Thread nie jest coś własnością webapp. Każde kolejne wdrożenie utworzy nową instancję klasy, która nigdy nie zostanie usunięta.

Skończysz z wyjątkami z powodu java.lang.OutOfMemoryError: PermGen space i po jakimś googlowaniu prawdopodobnie po prostu zwiększy -XX:MaxPermSize zamiast naprawić błąd.

Jeśli w końcu doświadczysz tych problemów, możesz aby określić, który wątek i klasa zachowują te odniesienia, użyj analizatora pamięci Eclipse i / lub wykonaj Przewodnik Franka Kievieta i followup .

Aktualizacja: ponownie odkrytywpis Alexa Vasseura na blogu , który pomógł mi wyśledzić kilka ThreadLocal problemów, które miałem.

 381
Author: Phil M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-27 22:42:09

Wiele frameworków używa Threadlocal do zachowania kontekstu związanego z bieżącym wątkiem. Na przykład, gdy bieżąca transakcja jest przechowywana w ThreadLocal, nie musisz przekazywać jej jako parametru przez każde wywołanie metody, na wypadek, gdyby ktoś na stosie potrzebował do niej dostępu. Aplikacje internetowe mogą przechowywać informacje o bieżącym żądaniu i sesji w ThreadLocal, dzięki czemu aplikacja ma łatwy dostęp do nich. Dzięki Guice możesz używać ThreadLocals podczas implementacji custom scopes dla wtryskiwanych obiektów (domyślne scopy serwletów Guice prawdopodobnie również ich używają).

Threadlocal są jednym z rodzajów globalnych zmiennych (choć nieco mniej złych, ponieważ są ograniczone do jednego wątku), więc należy zachować ostrożność podczas ich używania, aby uniknąć niepożądanych efektów ubocznych i wycieków pamięci. Zaprojektuj swoje API tak, aby wartości ThreadLocal zawsze były automatycznie czyszczone, gdy nie są już potrzebne i nie będzie nieprawidłowego użycia API możliwe (na przykład Jak to). ThreadLocals mogą być używane do czyszczenia kodu, a w niektórych rzadkich przypadkach są jedynym sposobem, aby coś zadziałało(mój obecny projekt miał dwa takie przypadki; są one udokumentowane tutaj pod "statyczne pola i zmienne globalne").

 125
Author: Esko Luontola,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-14 06:46:54

W języku Java, jeśli masz datum, które może się różnić w zależności od wątku, twoje wybory to przekazanie tego datum do każdej metody, która go potrzebuje( lub może potrzebować), lub powiązanie datum z wątkiem. Przekazywanie datum wszędzie może być wykonalne, jeśli wszystkie metody muszą już przekazywać wspólną zmienną "context".

Jeśli tak nie jest, możesz nie chcieć zaśmiecać podpisów metod dodatkowym parametrem. W świecie bez gwintowania możesz rozwiązać problem z Java odpowiednikiem zmiennej globalnej. W słowie wątkowym odpowiednikiem zmiennej globalnej jest zmienna wątkowa-lokalna.

 43
Author: user100464,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-03 20:20:39

Zasadniczo, gdy potrzebujesz wartości zmiennej zależnej od bieżącego wątku, a nie jest wygodne dołączanie wartości do wątku w inny sposób (na przykład podklasowanie wątku).

Typowy przypadek jest taki, gdy Inny framework stworzył wątek, w którym działa twój kod, np. kontener serwletów, lub gdy po prostu bardziej sensowne jest użycie ThreadLocal, ponieważ twoja zmienna jest wtedy "w swoim logicznym miejscu" (zamiast zmiennej wiszące na podklasie wątku lub w innej mapie hash).

Na mojej stronie, mam kilka dalszych dyskusji i przykładów, kiedy używać ThreadLocal , które mogą być również interesujące.

Niektórzy opowiadają się za używaniem ThreadLocal jako sposobu na dołączenie "identyfikatora wątku" do każdego wątku w pewnych algorytmach współbieżnych, w których potrzebny jest numer wątku (patrz np. Herlihy & Shavit). W takich przypadkach sprawdź, czy naprawdę otrzymujesz korzyść!

 13
Author: Neil Coffey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-03 23:50:05

Jest bardzo dobry przykład w książce współbieżność Javy w praktyce. Gdzie autor (Joshua Bloch ) wyjaśnia, w jaki sposób zamknięcie wątku jest jednym z najprostszych sposobów osiągnięcia bezpieczeństwa wątku, a ThreadLocal jest bardziej formalnym sposobem utrzymania zamknięcia wątku. W końcu wyjaśnia również, w jaki sposób ludzie mogą go nadużywać, używając go jako zmiennych globalnych.

Skopiowałem tekst ze wspomnianej książki, ale brakuje kodu 3.10, ponieważ nie jest to zbyt ważne, aby zrozumieć gdzie należy stosować ThreadLocal.

Zmienne lokalne wątku są często używane do zapobiegania współdzieleniu w projektach opartych na zmiennych Singletonach lub zmiennych globalnych. Na przykład aplikacja jednowątkowa może utrzymywać globalne połączenie z bazą danych, które jest inicjowane podczas uruchamiania, aby uniknąć konieczności przekazywania połączenia do każdej metody. Ponieważ połączenia JDBC mogą nie być bezpieczne dla wątków, wielowątkowa aplikacja, która używa połączenia globalnego bez dodatkowej koordynacji, nie jest bezpieczna dla wątków ani jedno, ani drugie. Używając ThreadLocal do przechowywania połączenia JDBC, jak w ConnectionHolder w Listing 3.10, każdy wątek będzie miał swoje własne połączenie.

ThreadLocal jest szeroko stosowany w implementacji frameworków aplikacji. Na przykład kontenery J2EE kojarzą kontekst transakcji z wykonującym wątkiem na czas trwania wywołania EJB. Jest to łatwo zaimplementowane przy użyciu statycznego wątku-lokalnego trzymającego kontekst transakcji: gdy kod frameworku musi określić, co to jest transakcja aktualnie uruchomiony, pobiera kontekst transakcji z tego wątku lokalnego. Jest to wygodne, ponieważ zmniejsza potrzebę przekazywania informacji o kontekście wykonania do każdej metody, ale łączy dowolny kod, który używa tego mechanizmu z frameworkiem.

Łatwo jest nadużywać ThreadLocal, traktując jego właściwość thread confinement jako licencję na używanie zmiennych globalnych lub jako sposób tworzenia" ukrytych " argumentów metody. Podobnie jak zmienne globalne, zmienne lokalne wątku mogą wielokrotnego użytku i wprowadzić Ukryte sprzęgła między klasami, a zatem powinny być używane ostrożnie.

 11
Author: Rakesh Chauhan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-28 14:28:38

Dokumentacja mówi to bardzo dobrze: "każdy wątek, który uzyskuje dostęp do zmiennej lokalnej wątku (za pomocą metody get lub set) ma własną, niezależnie zainicjalizowaną kopię zmiennej".

Używasz jednego, gdy każdy wątek musi mieć własną kopię czegoś. Domyślnie dane są współdzielone między wątkami.

 9
Author: RichieHindle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-27 13:31:34

Serwer Webapp może zachować pulę wątków, a var ThreadLocal powinien zostać usunięty przed odpowiedzią na klienta, więc bieżący wątek może być ponownie użyty przez następne żądanie.

 9
Author: znlyj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-29 11:58:13
  1. ThreadLocal w Javie został wprowadzony w JDK 1.2, ale później został uogólniony w JDK 1.5 W celu wprowadzenia bezpieczeństwa typu na zmiennej ThreadLocal.

  2. ThreadLocal może być skojarzony z zakresem wątku, cały kod, który jest wykonywany przez wątek ma dostęp do zmiennych ThreadLocal, ale dwa wątki nie mogą widzieć siebie nawzajem zmienna ThreadLocal.

  3. Każdy wątek posiada wyłączną kopię zmiennej ThreadLocal, która po thread finished or died, normally or due to any Exception, give threadlocal variable doesn ' t have any other live reference.

  4. Zmienne ThreadLocal w Javie są zazwyczaj prywatnymi polami statycznymi w klasach i zachowują swój stan wewnątrz wątku.

Czytaj więcej: http://javarevisited.blogspot.com/2012/05/how-to-use-threadlocal-in-java-benefits.html#ixzz2XltgbHTK

 8
Author: Abhijit Gaikwad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-13 09:59:38

Dwa przypadki użycia zmiennej threadlocal -
1 - gdy mamy wymóg powiązania stanu z wątkiem (np. ID użytkownika lub ID transakcji). Zwykle zdarza się to w przypadku aplikacji webowej, że każde żądanie przechodzące do servletu ma przypisany unikalny identyfikator transakcji.

// This class will provide a thread local variable which
// will provide a unique ID for each thread
class ThreadId {
    // Atomic integer containing the next thread ID to be assigned
    private static final AtomicInteger nextId = new AtomicInteger(0);

    // Thread local variable containing each thread's ID
    private static final ThreadLocal<Integer> threadId =
        ThreadLocal.<Integer>withInitial(()-> {return nextId.getAndIncrement();});

    // Returns the current thread's unique ID, assigning it if necessary
    public static int get() {
        return threadId.get();
    }
}

Zauważ, że tutaj metoda withInitial jest zaimplementowana przy użyciu wyrażenia lambda.
2-innym przypadkiem użycia jest sytuacja, gdy chcemy mieć bezpieczną instancję wątku i nie chcemy jej używać synchronizacja jako koszt wydajności z synchronizacją jest więcej. Jednym z takich przypadków jest stosowanie SimpleDateFormat. Ponieważ SimpleDateFormat nie jest bezpieczny dla wątku, więc musimy zapewnić mechanizm, aby był bezpieczny dla wątku.

public class ThreadLocalDemo1 implements Runnable {
    // threadlocal variable is created
    private static final ThreadLocal<SimpleDateFormat> dateFormat = new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue(){
            System.out.println("Initializing SimpleDateFormat for - " + Thread.currentThread().getName() );
            return new SimpleDateFormat("dd/MM/yyyy");
        }
    };

    public static void main(String[] args) {
        ThreadLocalDemo1 td = new ThreadLocalDemo1();
        // Two threads are created
        Thread t1 = new Thread(td, "Thread-1");
        Thread t2 = new Thread(td, "Thread-2");
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        System.out.println("Thread run execution started for " + Thread.currentThread().getName());
        System.out.println("Date formatter pattern is  " + dateFormat.get().toPattern());
        System.out.println("Formatted date is " + dateFormat.get().format(new Date()));
    } 

}
 6
Author: infoj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-29 15:21:25

Musisz być bardzo ostrożny z threadlocal wzór. Istnieje kilka głównych stron w dół, jak wspomniał Phil, ale jednym, który nie został wymieniony, jest upewnienie się, że kod, który ustawia kontekst ThreadLocal, nie jest "re-entrant."

Złe rzeczy mogą się zdarzyć, gdy kod ustawiający Informacje zostanie uruchomiony drugi lub trzeci raz, ponieważ informacje w Twoim wątku mogą zacząć mutować, gdy się tego nie spodziewałeś. Więc upewnij się, że informacje ThreadLocal nie zostały ustawione zanim ustawisz to jeszcze raz.

 4
Author: Jeff Richley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-23 18:50:09

Nie ma tu nic nowego, ale odkryłem dzisiaj, że ThreadLocal jest bardzo przydatny przy użyciu walidacji Bean w aplikacji internetowej. Komunikaty walidacji są zlokalizowane, ale domyślnie używa się Locale.getDefault(). Możesz skonfigurować Validator z innym MessageInterpolator, ale nie ma sposobu, aby określić Locale podczas wywoływania validate. Możesz więc utworzyć statyczny ThreadLocal<Locale> (lub jeszcze lepiej, ogólny kontener z innymi rzeczami, które możesz potrzebować ThreadLocal, a następnie mieć swój własny MessageInterpolator Wybierz Locale z tego. Następnym krokiem jest napisz ServletFilter, który używa wartości sesji lub request.getLocale(), aby wybrać Ustawienia regionalne i zapisać je w referencji ThreadLocal.

 3
Author: Colselaw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-31 01:37:35

Jak wspomniano przez @ unknown (google), jego użycie polega na zdefiniowaniu zmiennej globalnej, w której wartość może być unikalna w każdym wątku. To zwyczaje zazwyczaj pociąga za sobą przechowywanie pewnego rodzaju informacji kontekstowych, które są powiązane z bieżącym wątkiem wykonania.

Używamy go w środowisku Java EE do przekazywania tożsamości użytkownika klasom, które nie są świadome Java EE (nie mają dostępu do HttpSession, ani EJB SessionContext). W ten sposób kod, który sprawia, że korzystanie z tożsamości dla operacje oparte na zabezpieczeniach mogą uzyskać dostęp do tożsamości z dowolnego miejsca, bez konieczności jawnego przekazywania jej w każdym wywołaniu metody.

Cykl request / response operacji w większości wywołań Java EE sprawia, że ten typ użycia jest łatwy, ponieważ daje dobrze zdefiniowane punkty wejścia i wyjścia do ustawiania i wyłączania ThreadLocal.

 3
Author: Robin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-27 08:12:53

ThreadLocal zapewni dostęp do mutowalnego obiektu przez wielokrotność wątki w niezsynchronizowanej metodzie są zsynchronizowane, czyli dokonywanie zmienny obiekt, który ma być niezmienny w metodzie.

to uzyskuje się poprzez podanie nowej instancji mutowalnego obiektu dla każdego wątku spróbuj się do niego dostać. Jest to więc lokalna kopia dla każdego wątku. To jest jakiś hack na dokonywanie zmiennej instancji w metodzie, która ma być dostępna jak zmienna lokalna. Jak wiadomo zmienna lokalna metody jest tylko dostępne do wątku, jedna różnica to; zmienne lokalne metody nie będą dostępne dla wątku po zakończeniu wykonywania metody, gdzie jako mutable obiekt współdzielony z threadlocal będzie dostępny w wielu metody, dopóki nie posprzątamy.

Z Definicji:

Klasa ThreadLocal w Javie umożliwia tworzenie zmiennych, które mogą być czytane i pisane tylko przez ten sam wątek. Tak więc, nawet jeśli dwa wątki wykonują ten sam kod, a kod ma odniesienie do Zmienna ThreadLocal, wtedy dwa wątki nie mogą widzieć siebie nawzajem Zmienne ThreadLocal.

Każdy Thread w Javie zawiera w sobie ThreadLocalMap.
Gdzie

Key = One ThreadLocal object shared across threads.
value = Mutable object which has to be used synchronously, this will be instantiated for each thread.

Osiągnięcie ThreadLocal:

Teraz Utwórz klasę wrappera dla ThreadLocal, która będzie trzymać zmienny obiekt jak poniżej (z lub bez initialValue()).
teraz getter i setter tego opakowania będą działać na instancji threadlocal zamiast obiekt zmienny.

Jeśli getter () threadlocal nie znalazł żadnej wartości w threadlocalmap Thread; wtedy wywoła initialValue (), aby uzyskać jego prywatną kopię w odniesieniu do wątku.

class SimpleDateFormatInstancePerThread {

    private static final ThreadLocal<SimpleDateFormat> dateFormatHolder = new ThreadLocal<SimpleDateFormat>() {

        @Override
        protected SimpleDateFormat initialValue() {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd") {
                UUID id = UUID.randomUUID();
                @Override
                public String toString() {
                    return id.toString();
                };
            };
            System.out.println("Creating SimpleDateFormat instance " + dateFormat +" for Thread : " + Thread.currentThread().getName());
            return dateFormat;
        }
    };

    /*
     * Every time there is a call for DateFormat, ThreadLocal will return calling
     * Thread's copy of SimpleDateFormat
     */
    public static DateFormat getDateFormatter() {
        return dateFormatHolder.get();
    }

    public static void cleanup() {
        dateFormatHolder.remove();
    }
}

Teraz wrapper.getDateFormatter() wywoła threadlocal.get(), a to sprawdzi currentThread.threadLocalMap zawiera tę instancję (threadlocal).
Jeśli tak, zwróć wartość (SimpleDateFormat) dla odpowiedniej instancji threadlocal
w przeciwnym razie dodaj mapę za pomocą tej instancji threadlocal, initialValue ().

Oto bezpieczeństwo wątku osiągnięte na tej mutowalnej klasie; przez każdy wątek pracuje z własną mutowalną instancją, ale z tą samą instancją ThreadLocal. Oznacza, że wszystkie wątki będą miały tę samą instancję ThreadLocal jako klucz, ale inną instancję SimpleDateFormat jako wartość.

Https://github.com/skanagavelu/yt.tech/blob/master/src/ThreadLocalTest.java

 3
Author: Kanagavelu Sugumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-07 05:29:06

Kiedy?

Gdy obiekt nie jest bezpieczny dla wątku, zamiast synchronizacji, która utrudnia skalowalność, daj jeden obiekt do każdego wątku i zachowaj jego zakres wątku, który jest ThreadLocal. Jednym z najczęściej używanych, ale nie bezpiecznych dla wątków obiektów są Połączenie z bazą danych i JMSConnection.

Jak ?

Jednym z przykładów jest Spring Framework mocno wykorzystuje ThreadLocal do zarządzania transakcjami za kulisami, utrzymując te obiekty połączeń w zmiennych ThreadLocal. Na wysokim poziomie, po uruchomieniu transakcji pobiera połączenie ( i wyłącza automatyczne zatwierdzanie) i zachowuje je w trybie ThreadLocal. przy kolejnych wywołaniach db używa tego samego połączenia do komunikacji z db. Na końcu pobiera połączenie z ThreadLocal i zatwierdza (lub wycofuje ) transakcję i zwalnia połączenie.

Myślę, że log4j używa również ThreadLocal do utrzymywania MDC.

 3
Author: Limestone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-27 03:10:49

ThreadLocal jest przydatny, gdy chcesz mieć jakiś stan, który nie powinien być współdzielony między różnymi wątkami, ale powinien być dostępny z każdego wątku przez cały jego okres użytkowania.

Jako przykład, wyobraź sobie aplikację internetową, w której każde żądanie jest obsługiwane przez inny wątek. Wyobraź sobie, że dla każdego żądania potrzebujesz kilkukrotnego fragmentu danych, co jest dość kosztowne w obliczeniu. Jednak dane te mogły ulec zmianie Dla każdego przychodzącego żądania, co oznacza, że nie można użyć zwykłego cache. Prostym, szybkim rozwiązaniem tego problemu byłoby posiadanie zmiennej ThreadLocal, która przechowuje dostęp do tych danych, tak aby trzeba było je obliczyć tylko raz dla każdego żądania. Oczywiście problem ten można rozwiązać również bez użycia ThreadLocal, ale wymyśliłem go dla celów ilustracyjnych.

To powiedziawszy, miej na uwadze, że ThreadLocalS są zasadniczo formą Państwa globalnego. W rezultacie ma wiele innych implikacji i powinien być stosowany dopiero po rozważeniu wszystkich innych możliwych rozwiązań.

 2
Author: Dimos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-16 11:28:11

Thread-zmienne lokalne są często używane, aby zapobiec współdzieleniu w projektach opartych na zmienne Singletony lub zmienne globalne.

Może być używany w scenariuszach takich jak tworzenie oddzielnego połączenia JDBC dla każdego wątku, gdy nie używasz puli połączeń.

private static ThreadLocal<Connection> connectionHolder
           = new ThreadLocal<Connection>() {
      public Connection initialValue() {
           return DriverManager.getConnection(DB_URL);
          }
     };

public static Connection getConnection() {
      return connectionHolder.get();
} 

Wywołanie getConnection zwróci połączenie powiązane z tym wątkiem.To samo można zrobić z innymi właściwościami, takimi jak dateformat, kontekst transakcji, których nie chcesz udostępniać między wątkami.

Mogłeś również użyć zmiennych lokalnych do tego samego, ale te zasoby zwykle zajmują czas w tworzeniu, więc nie chcesz tworzyć ich ponownie i ponownie za każdym razem, gdy wykonujesz z nimi jakąś logikę biznesową. Jednak wartości ThreadLocal są przechowywane w samym obiekcie thread i gdy tylko wątek zostanie usunięty, te wartości również znikną.

Ten link bardzo dobrze wyjaśnia użycie ThreadLocal.

 2
Author: bpjoshi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-30 07:58:44

Od wydania Javy 8 istnieje bardziej deklaratywny sposób inicjalizacji ThreadLocal:

ThreadLocal<Cipher> local = ThreadLocal.withInitial(() -> "init value");

Do wydania Javy 8 trzeba było wykonać następujące czynności:

ThreadLocal<String> local = new ThreadLocal<String>(){
    @Override
    protected String initialValue() {
        return "init value";
    }
};

Ponadto, jeśli metoda instancji (konstruktor, metoda fabryczna) klasy, która jest używana dla ThreadLocal, nie przyjmuje żadnych parametrów, można po prostu użyć referencji do metod (wprowadzonych w Javie 8):

class NotThreadSafe {
    // no parameters
    public NotThreadSafe(){}
}

ThreadLocal<NotThreadSafe> container = ThreadLocal.withInitial(NotThreadSafe::new);

Uwaga: Ocena jest leniwa, ponieważ mijasz java.util.function.Supplier lambda, która jest oceniana tylko wtedy, gdy ThreadLocal#get jest wywołana, ale wartość nie był wcześniej oceniany.

 2
Author: Andrii Abramov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-28 14:44:39

Buforowanie, czasami trzeba obliczyć tę samą wartość dużo czasu, więc zapisując ostatni zestaw wejść do metody i wynik można przyspieszyć kod. Korzystając z lokalnego magazynu wątków, unikasz myślenia o blokowaniu.

 0
Author: Ian Ringrose,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-15 17:19:01

ThreadLocal to specjalnie aprowizowana przez JVM funkcja zapewniająca izolowaną przestrzeń dyskową tylko dla wątków. podobnie jak wartość zmiennej object scoped są powiązane tylko z daną instancją klasy. każdy obiekt ma swoje jedyne wartości i nie widzą siebie nawzajem wartości. tak jest pojęcie threadlocal zmiennych, są one lokalne do wątku w sensie instancji obiektów inny wątek z wyjątkiem tego, który go stworzył, nie może go zobaczyć. Zobacz Tutaj

import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;


public class ThreadId {
private static final AtomicInteger nextId = new AtomicInteger(1000);

// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> threadId = ThreadLocal.withInitial(() -> nextId.getAndIncrement());


// Returns the current thread's unique ID, assigning it if necessary
public static int get() {
    return threadId.get();
}

public static void main(String[] args) {

    new Thread(() -> IntStream.range(1, 3).forEach(i -> {
        System.out.println(Thread.currentThread().getName() + " >> " + new ThreadId().get());
    })).start();

    new Thread(() -> IntStream.range(1, 3).forEach(i -> {
        System.out.println(Thread.currentThread().getName() + " >> " + new ThreadId().get());
    })).start();

    new Thread(() -> IntStream.range(1, 3).forEach(i -> {
        System.out.println(Thread.currentThread().getName() + " >> " + new ThreadId().get());
    })).start();

}
}
 0
Author: Ajay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-30 14:09:57

Threadlocal zapewnia bardzo łatwy sposób na osiągnięcie wielokrotnego użytku obiektów przy zerowym koszcie.

Miałem sytuację, w której wiele wątków tworzyło obraz mutable cache, przy każdym powiadomieniu o aktualizacji.

Użyłem Threadlocal na każdym wątku, a następnie każdy wątek musiałby tylko zresetować stary obraz, a następnie zaktualizować go ponownie z pamięci podręcznej przy każdym powiadomieniu o aktualizacji.

Zwykłe obiekty wielokrotnego użytku z puli obiektów mają związane z nimi koszty bezpieczeństwa wątku, podczas gdy to podejście nie ma żadnego.

 0
Author: Dev Amitabh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-12 03:00:41

Klasa ThreadLocal w Javie umożliwia tworzenie zmiennych, które mogą być odczytywane i zapisywane tylko przez ten sam wątek. Tak więc, nawet jeśli dwa wątki wykonują ten sam kod, a kod ma odniesienie do zmiennej ThreadLocal, to dwa wątki nie mogą zobaczyć swoich zmiennych ThreadLocal.

Czytaj więcej

 0
Author: Pritesh Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-04 13:18:08