JavaRush /Blog Java /Random-PL /Przerwa kawowa #160. Głęboko zanurz się w Java ThreadLoca...

Przerwa kawowa #160. Głęboko zanurz się w Java ThreadLocal. Klasa skanera w Javie

Opublikowano w grupie Random-PL

Zanurz się głęboko w Java ThreadLocal

Źródło: Devgenios Dzisiaj dowiesz się o ThreadLocal, jednej z powszechnych klas używanych przy tworzeniu aplikacji Java. Przerwa kawowa #160.  Głęboko zanurz się w Java ThreadLocal.  Klasa skanera w Javie - 1

Co to jest ThreadLocal?

Klasa ThreadLocal przechowuje zmienne lokalne dla wątków. Zmienne te są izolowane między różnymi wątkami i można uzyskać do nich dostęp tylko za pośrednictwem ich własnego wątku. Przypadki użycia ThreadLocal :
  1. Izoluj dane między wątkami.
  2. Zarządzanie sesjami dla połączeń z bazami danych.
  3. Przechowywanie informacji o transakcjach wątku.

Jak korzystać z ThreadLocal?

Spójrzmy na prosty przykład.
public static void main(String[] args) {
    //Создаем ThreadLocal
    ThreadLocal<String> local = new ThreadLocal<>();
    //Создаем новый класс Random
    Random random = new Random();
    //Создаем 5 потоков
    IntStream.range(0, 5).forEach(a-> new Thread(()-> {
        //Присваиваем oznaczający каждому потоку
        local.set(a+"  "+random.nextInt(100));
        System.out.println("Thread number and its local value  "+ local.get());
    }).start());
}
W powyższym kodzie tworzymy klasę ThreadLocal , tworzymy 5 wątków, przypisujemy wartość do ThreadLocal w każdym wątku i drukujemy. Podczas wyprowadzania otrzymujemy: Przerwa kawowa #160.  Głęboko zanurz się w Java ThreadLocal.  Klasa skanera w Javie - 2

Co kryje się pod maską?

Jeśli przyjrzysz się uważnie, zobaczysz, że w ThreadLocal istnieją dwie ważne metody z tego przykładowego kodu.
  • publiczny T get() {}

  • publiczny zestaw pustych wartości (wartość T) {}

Przyjrzyjmy się metodzie ustawiającej w kodzie źródłowym ThreadLocal :
public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
}
Metoda setter najpierw pobiera bieżący wątek i wywołuje metodę getMap() w celu pobrania klasy ThreadLocalMap . Jeśli mapa istnieje, przyjmij bieżący strumień t jako klucz, parametr wejściowy jako wartość i ustaw parę {klucz:wartość} na map. Jeśli nie, utwórz mapę . Teraz możesz mieć pytanie - co to jest ThreadLocalMap ?
static class ThreadLocalMap {
   /**
    * The entries in this hash map extend WeakReference, using
    * its main ref field as the key (which is always a
    * ThreadLocal object).  Note that null keys (i.e. entry.get()
    * == null) mean that the key is no longer referenced, so the
    * entry can be expunged from table.  Such entries are referred to
    * as "stale entries" in the code that follows.
    */
    static class Entry extends WeakReference<ThreadLocal<?>> {
       /** The value associated with this ThreadLocal. */
       Object value;
       Entry(ThreadLocal<?> k, Object v) {
           super(k);
           value = v;
       }
    }
}
ThreadLocalMap to wewnętrzna klasa statyczna w ThreadLocal , która definiuje klasę Entry do przechowywania danych. Entry używa instancji ThreadLocal jako klucza i ustawia wartość, którą przekazujemy. Jeśli w tym momencie brzmi to zbyt zagmatwanie, pamiętaj, że to klasa Entry w ThreadLocalMap faktycznie przechowuje wartości. Aby pobrać dane z ThreadLocal, używamy metody gettera :
public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
}
W metodzie gettera użyjemy currentThread jako klucza do pobrania ThreadLocalMap . Następnie map wykona funkcję getEntry() w oparciu o instancję ThreadLocal i zwróci instancję Entry , a następnie zapisaną wartość. Oto diagram, który pomoże Ci to rozgryźć: Przerwa kawowa #160.  Głęboko zanurz się w Java ThreadLocal.  Klasa skanera w Javie - 3Przerwa kawowa #160.  Głęboko zanurz się w Java ThreadLocal.  Klasa skanera w Javie - 4
  1. Każdy wątek utrzymuje odwołanie do ThreadLocalMap .

  2. ThreadLocalMap jest wewnętrzną klasą statyczną ThreadLocal i używa klasy Entry do przechowywania.

  3. Klucz ThreadLocalMap jest instancją ThreadLocal i może mieć wiele ThreadLocals .

  4. Sam ThreadLocal nie przechowuje wartości, ale jest kluczem dla wątku, który pomoże uzyskać wartość z ThreadLocalMap .

Pamiętaj, że lepiej usunąć ThreadLocal , aby uniknąć OOM (Błąd braku pamięci) z powodu „słabego” odniesienia w klasie Entry .

Klasa skanera w Javie

Źródło: Medium Ten post pomoże Ci zapoznać się z klasą Scanner w Javie. Przerwa kawowa #160.  Głęboko zanurz się w Java ThreadLocal.  Klasa skanera w Javie - 5Klasa Scanner w Javie to klasa, której używamy, gdy chcemy uzyskać wartość od użytkownika. Najłatwiej to zrozumieć na przykładach, więc spójrzmy na to jaśniej. Utworzenie klasy Scanner to jeden z trzech kroków, jakie wykonujemy, aby uzyskać wartość od użytkownika. Pierwszym krokiem jest utworzenie obiektu z klasy skanera.
Scanner scan=new Scanner(System.in);
Teraz mamy obiekt skanera. Obiekt ten będzie miał właściwości Scanner z klasy Scanner . Już po pierwszym kroku użytkownik może wprowadzić żądaną wartość, jednak jeśli nie poprowadzimy użytkownika i nie wyświetlimy wartości w konsoli lub w aplikacji, nie będzie to zbyt dobre pod względem użyteczności. Dlatego lepiej poinformować i poinstruować użytkownika:
System.out.println("Please enter your name");
String name=scan.next();
System.out.println("Your Name:"+name);
W pierwszej linijce pytamy użytkownika, czego od niego chcemy. Właściwie nie ma to nic wspólnego ze skanerem, ale zawsze dobrze jest dać wskazówki użytkownikom. W drugiej linii przypiszemy wartość, którą użytkownik wprowadzi do danych i zapiszemy ją, abyśmy mogli z niej później skorzystać. W ostatniej linijce widzimy, że otrzymaną od użytkownika wartość możemy wykorzystać według własnego uznania. Dodajmy jeszcze kilka szczegółów do naszego kodu:
System.out.println("Please enter your last name");

String lastName=scan.next();

System.out.println("Your Name " + name + " " + "Your Last Name" + lastName);
Zasadniczo powtórzyliśmy dwie poprzednie linie, zapytaliśmy użytkownika o wartość i zapisaliśmy ją. Teraz w ostatniej linii użyliśmy dwóch wartości, które pobraliśmy od użytkownika i które teraz są używane razem.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION