Глибоке занурення у Java ThreadLocal
Джерело: Devgenios Сьогодні ви дізнаєтеся про ThreadLocal - один з поширених класів, що використовуються при розробці Java-додатків.![Кава-брейк #160. Глибоке занурення Java ThreadLocal. Клас Scanner в Java - 1](https://cdn.javarush.com/images/article/8d73e480-aa59-4ac4-b001-b21ead03ef81/800.jpeg)
Що таке ThreadLocal?
Клас ThreadLocal зберігає локальні змінні потоків. Ці змінні ізольовані між різними потоками і можуть бути доступними лише своєму власному потоку. Варіанти застосування ThreadLocal :- Ізоляція даних між потоками.
- Управління сесіями для підключення до бази даних.
- Зберігання трансакційної інформації потоку.
Як використовувати ThreadLocal?
Давайте розглянемо найпростіший приклад.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(()-> {
//Присваиваем значення каждому потоку
local.set(a+" "+random.nextInt(100));
System.out.println("Thread number and its local value "+ local.get());
}).start());
}
У наведеному вище коді ми створюємо клас ThreadLocal , створюємо 5 потоків, присвоюємо значення ThreadLocal у кожному потоці та виводимо на друк. При виводі отримуємо: ![Кава-брейк #160. Глибоке занурення Java ThreadLocal. Клас Scanner в Java - 2](https://cdn.javarush.com/images/article/f730961e-ff0c-4c7f-8af7-3ac6647609df/256.jpeg)
Що під капотом?
Якщо уважно подивитися, то можна зрозуміти, що в ThreadLocal з цього прикладу коду є два важливі методи.-
public T get() {}
-
public void set (T value) {}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
Метод setter спочатку отримує поточний потік і викликає метод getMap() отримання класу ThreadLocalMap . Якщо map існує, візьміть поточний потік t як ключ, вхідний параметр як значення та встановіть пару {key:value} у map. Якщо ні, створіть map . Тепер у вас може постати питання - що таке 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 — це внутрішній статичний клас ThreadLocal , що визначає клас Entry для зберігання даних. Entry використовує екземпляр ThreadLocal як ключ і встановлює значення, яке ми передаємо. Якщо на даному етапі це звучить занадто заплутано , просто запам'ятайте, що саме клас Entry ThreadLocalMap виконує фактичне зберігання значень. Щоб отримати дані з ThreadLocal , ми використовуємо метод getter :
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();
}
У методі getter ми будемо використовувати currentThread як ключ для отримання ThreadLocalMap . Потім map отримає getEntry() на основі екземпляра ThreadLocal і поверне екземпляр Entry , а потім збережене значення. Ось схема, яка допоможе розібратися: ![Кава-брейк #160. Глибоке занурення Java ThreadLocal. Клас Scanner в Java - 3](https://cdn.javarush.com/images/article/e34c044d-2e96-4895-8ba2-63a2ffe15c33/512.jpeg)
![Кава-брейк #160. Глибоке занурення Java ThreadLocal. Клас Scanner в Java - 4](https://cdn.javarush.com/images/article/cb5290ba-4df5-44f6-b0e1-7b8a30f90020/800.jpeg)
-
Кожен потік підтримує посилання ThreadLocalMap .
-
ThreadLocalMap є внутрішнім статичним класом ThreadLocal та використовує клас Entry для зберігання.
-
Ключ ThreadLocalMap є екземпляром ThreadLocal і може мати декілька ThreadLocal .
-
Сам ThreadLocal не зберігає значення, але це ключ для потоку, який допоможе отримати значення ThreadLocalMap .
Клас Scanner в Java
Джерело: Medium Ця публікація допоможе вам ознайомитися з класом Scanner у Java.![Кава-брейк #160. Глибоке занурення Java ThreadLocal. Клас Scanner в Java - 5](https://cdn.javarush.com/images/article/84b89dcc-0382-4028-b986-3e239ad8512c/800.jpeg)
Scanner scan=new Scanner(System.in);
Тепер ми маємо об'єкт сканера. Цей об'єкт матиме властивості Scanner із класу Scanner . Після першого кроку користувач може ввести бажане значення, але якщо ми не направимо користувача і не відобразимо значення в консолі або в додатку, це буде не дуже добре з точки зору зручності. Тому краще поінформувати та направити користувача:
System.out.println("Please enter your name");
String name=scan.next();
System.out.println("Your Name:"+name);
У першому рядку ми запитуємо користувача, що ми хочемо. Насправді це не має нічого спільного зі сканером, але завжди корисно підказувати своїм користувачам. У другому рядку ми надамо значення, яке користувач введе в дані, і збережемо його, щоб ми могли використовувати його пізніше. В останньому рядку ми бачимо, що можемо використовувати отримане від користувача значення на власний розсуд. Давайте додамо до нашого коду ще кілька деталей:
System.out.println("Please enter your last name");
String lastName=scan.next();
System.out.println("Your Name " + name + " " + "Your Last Name" + lastName);
Власне кажучи, ми повторабо два попередні рядки, запитабо значення у користувача і зберегли його. Тепер у останньому рядку ми використовували два значення, які взяли у користувача, і які тепер використовуються разом.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ