Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprenda Threadlocal | Melhores Práticas de Multithreading
Multithreading em Java

bookThreadlocal

ThreadLocal permite evitar mecanismos relacionados à multithread, como sincronização, pois os dados de ThreadLocal são acessíveis apenas dentro de uma única thread.

Imagine uma aplicação bancária onde cada cliente possui sua própria conta. Se vários clientes estiverem usando a aplicação simultaneamente, as contas deles devem permanecer separadas. Utilizando ThreadLocal, cada thread (cliente) recebe sua própria instância de dados (conta), garantindo que não interfira em outras threads.

Como usar ThreadLocal

ThreadLocal fornece um método get() e um método set(), ambos autoexplicativos.

get() - recupera o valor da variável ThreadLocal.

ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
threadLocal.get();

set() - define o valor para a variável ThreadLocal.

ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
threadLocal.set(10);

Vamos criar um programa para comparar uma variável simples com ThreadLocal.

Cada thread terá seu próprio threadLocalCounter distinto, enquanto o valor de sharedCounter será alterado e compartilhado entre todas as threads. A saída do programa demonstrará que os valores de threadLocalCounter são únicos para cada thread, enquanto sharedCounter refletirá um resultado comum para todas as threads, que pode variar dependendo da ordem em que as threads são executadas.

ThreadLocalComparison.java

ThreadLocalComparison.java

CounterTask.java

CounterTask.java

copy
12345678910111213141516
public class ThreadLocalComparison { public static void main(String[] args) { CounterTask counterTask = new CounterTask(); // Create threads for demonstrating the behavior Thread thread1 = new Thread(counterTask); Thread thread2 = new Thread(counterTask); Thread thread3 = new Thread(counterTask); // Start the threads thread1.start(); thread2.start(); thread3.start(); } }

E após a execução deste programa, obtemos o seguinte resultado:

Shared Counter: 1
Shared Counter: 2
Shared Counter: 3
ThreadLocal Counter: 1
ThreadLocal Counter: 1
ThreadLocal Counter: 1

Como pode ser observado, a variável sharedCounter é incrementada entre diferentes threads, enquanto a variável threadLocalCounter mantém o mesmo valor em cada thread, pois cada thread possui sua própria instância de threadLocalCounter, que é independente das demais threads.

Como pode ser observado, o código inclui um método estático ThreadLocal.withInitial() que define um valor inicial para a variável quando ela é criada.

ThreadLocal<Integer> threadLocalCounter = ThreadLocal.withInitial(() -> 0);

O método remove() na classe ThreadLocal é utilizado para remover o valor associado à thread atual.

ThreadLocalTask.java

ThreadLocalTask.java

ThreadLocalRemoveExample.java

ThreadLocalRemoveExample.java

copy
123456789101112131415161718192021
class ThreadLocalTask implements Runnable { // Define a `ThreadLocal` variable with an initial value private static ThreadLocal<String> threadLocalValue = new ThreadLocal<>(); @Override public void run() { // Set a value in the `ThreadLocal` for this thread String threadName = Thread.currentThread().getName(); threadLocalValue.set(threadName + " Value"); // Print the current value System.out.println(threadName + " - ThreadLocal Value before removal: " + threadLocalValue.get()); // Remove the value associated with the current thread threadLocalValue.remove(); // Print the value after removal System.out.println(threadName + " - ThreadLocal Value after removal: " + threadLocalValue.get()); } }

Como resultado da execução do programa:

Thread-0 - ThreadLocal Value before removal: Thread-0 Value
Thread-0 - ThreadLocal Value after removal: null
Thread-1 - ThreadLocal Value before removal: Thread-1 Value
Thread-1 - ThreadLocal Value after removal: null

O programa atribui um valor exclusivo ao ThreadLocal para cada thread e exibe esse valor antes e depois que o método remove() é invocado. Após remover o valor com remove(), o ThreadLocal retorna null em chamadas subsequentes ao get().

Note
Nota

Os dados que estão em ThreadLocal não são excluídos automaticamente e devem ser excluídos explicitamente!

Por que preciso liberar um valor?

Liberar um valor é fundamental para evitar vazamentos de memória. O ThreadLocal mantém valores vinculados às threads em um mapa especial que é associado às threads. Se um valor não for removido, ele permanece no mapa mesmo após o uso da thread ser concluído, levando à permanência de objetos desnecessários na memória e, consequentemente, resultando em vazamentos de memória.

1. Qual é o principal problema que o uso de ThreadLocal resolve?

2. Qual é o valor inicial de uma variável ThreadLocal quando ela é criada usando o método withInitial()?

3. O que acontece se você não chamar o método remove() para uma variável ThreadLocal em threads de longa duração?

question mark

Qual é o principal problema que o uso de ThreadLocal resolve?

Select the correct answer

question mark

Qual é o valor inicial de uma variável ThreadLocal quando ela é criada usando o método withInitial()?

Select the correct answer

question mark

O que acontece se você não chamar o método remove() para uma variável ThreadLocal em threads de longa duração?

Select the correct answer

Tudo estava claro?

Como podemos melhorá-lo?

Obrigado pelo seu feedback!

Seção 4. Capítulo 4

Pergunte à IA

expand

Pergunte à IA

ChatGPT

Pergunte o que quiser ou experimente uma das perguntas sugeridas para iniciar nosso bate-papo

Awesome!

Completion rate improved to 3.33

bookThreadlocal

Deslize para mostrar o menu

ThreadLocal permite evitar mecanismos relacionados à multithread, como sincronização, pois os dados de ThreadLocal são acessíveis apenas dentro de uma única thread.

Imagine uma aplicação bancária onde cada cliente possui sua própria conta. Se vários clientes estiverem usando a aplicação simultaneamente, as contas deles devem permanecer separadas. Utilizando ThreadLocal, cada thread (cliente) recebe sua própria instância de dados (conta), garantindo que não interfira em outras threads.

Como usar ThreadLocal

ThreadLocal fornece um método get() e um método set(), ambos autoexplicativos.

get() - recupera o valor da variável ThreadLocal.

ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
threadLocal.get();

set() - define o valor para a variável ThreadLocal.

ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
threadLocal.set(10);

Vamos criar um programa para comparar uma variável simples com ThreadLocal.

Cada thread terá seu próprio threadLocalCounter distinto, enquanto o valor de sharedCounter será alterado e compartilhado entre todas as threads. A saída do programa demonstrará que os valores de threadLocalCounter são únicos para cada thread, enquanto sharedCounter refletirá um resultado comum para todas as threads, que pode variar dependendo da ordem em que as threads são executadas.

ThreadLocalComparison.java

ThreadLocalComparison.java

CounterTask.java

CounterTask.java

copy
12345678910111213141516
public class ThreadLocalComparison { public static void main(String[] args) { CounterTask counterTask = new CounterTask(); // Create threads for demonstrating the behavior Thread thread1 = new Thread(counterTask); Thread thread2 = new Thread(counterTask); Thread thread3 = new Thread(counterTask); // Start the threads thread1.start(); thread2.start(); thread3.start(); } }

E após a execução deste programa, obtemos o seguinte resultado:

Shared Counter: 1
Shared Counter: 2
Shared Counter: 3
ThreadLocal Counter: 1
ThreadLocal Counter: 1
ThreadLocal Counter: 1

Como pode ser observado, a variável sharedCounter é incrementada entre diferentes threads, enquanto a variável threadLocalCounter mantém o mesmo valor em cada thread, pois cada thread possui sua própria instância de threadLocalCounter, que é independente das demais threads.

Como pode ser observado, o código inclui um método estático ThreadLocal.withInitial() que define um valor inicial para a variável quando ela é criada.

ThreadLocal<Integer> threadLocalCounter = ThreadLocal.withInitial(() -> 0);

O método remove() na classe ThreadLocal é utilizado para remover o valor associado à thread atual.

ThreadLocalTask.java

ThreadLocalTask.java

ThreadLocalRemoveExample.java

ThreadLocalRemoveExample.java

copy
123456789101112131415161718192021
class ThreadLocalTask implements Runnable { // Define a `ThreadLocal` variable with an initial value private static ThreadLocal<String> threadLocalValue = new ThreadLocal<>(); @Override public void run() { // Set a value in the `ThreadLocal` for this thread String threadName = Thread.currentThread().getName(); threadLocalValue.set(threadName + " Value"); // Print the current value System.out.println(threadName + " - ThreadLocal Value before removal: " + threadLocalValue.get()); // Remove the value associated with the current thread threadLocalValue.remove(); // Print the value after removal System.out.println(threadName + " - ThreadLocal Value after removal: " + threadLocalValue.get()); } }

Como resultado da execução do programa:

Thread-0 - ThreadLocal Value before removal: Thread-0 Value
Thread-0 - ThreadLocal Value after removal: null
Thread-1 - ThreadLocal Value before removal: Thread-1 Value
Thread-1 - ThreadLocal Value after removal: null

O programa atribui um valor exclusivo ao ThreadLocal para cada thread e exibe esse valor antes e depois que o método remove() é invocado. Após remover o valor com remove(), o ThreadLocal retorna null em chamadas subsequentes ao get().

Note
Nota

Os dados que estão em ThreadLocal não são excluídos automaticamente e devem ser excluídos explicitamente!

Por que preciso liberar um valor?

Liberar um valor é fundamental para evitar vazamentos de memória. O ThreadLocal mantém valores vinculados às threads em um mapa especial que é associado às threads. Se um valor não for removido, ele permanece no mapa mesmo após o uso da thread ser concluído, levando à permanência de objetos desnecessários na memória e, consequentemente, resultando em vazamentos de memória.

1. Qual é o principal problema que o uso de ThreadLocal resolve?

2. Qual é o valor inicial de uma variável ThreadLocal quando ela é criada usando o método withInitial()?

3. O que acontece se você não chamar o método remove() para uma variável ThreadLocal em threads de longa duração?

question mark

Qual é o principal problema que o uso de ThreadLocal resolve?

Select the correct answer

question mark

Qual é o valor inicial de uma variável ThreadLocal quando ela é criada usando o método withInitial()?

Select the correct answer

question mark

O que acontece se você não chamar o método remove() para uma variável ThreadLocal em threads de longa duração?

Select the correct answer

Tudo estava claro?

Como podemos melhorá-lo?

Obrigado pelo seu feedback!

Seção 4. Capítulo 4
some-alt