Entendendo o ThreadLocal em Java

Por Gaspar Barancelli Junior em 22 de julho de 2024
Imagem ilustrativa sobre o post Entendendo o ThreadLocal em Java

O ThreadLocal é uma classe do Java que permite criar variáveis que são acessíveis apenas pelo thread que as possui. Ou seja, cada thread tem sua própria cópia dessa variável, permitindo isolar dados entre threads sem a necessidade de sincronização explícita. Este recurso é especialmente útil em cenários onde múltiplos threads precisam de acesso exclusivo a determinadas informações. Isso significa que mesmo que várias threads executem o mesmo código que acessa um ThreadLocal, cada thread terá sua própria instância separada da variável.

Exemplo 1: Usando ThreadLocal para Armazenar IDs de Sessão

Vamos considerar um cenário simples onde precisamos armazenar um ID de sessão único para cada thread. Isso pode ser útil em uma aplicação web onde cada requisição é tratada por um thread diferente.

public class SessionManager {

    private static final ThreadLocal<String> SESSION_ID = ThreadLocal.withInitial(() -> "defaultSessionId");

    public static String getSessionId() {
        return SESSION_ID.get();
    }

    public static void setSessionId(String id) {
        SESSION_ID.set(id);
    }

    public static void main(String[] args) {
        Runnable task1 = () -> {
            setSessionId("session1");
            System.out.println("Task1 Session ID: " + getSessionId());
        };

        Runnable task2 = () -> {
            setSessionId("session2");
            System.out.println("Task2 Session ID: " + getSessionId());
        };

        Thread thread1 = new Thread(task1);
        Thread thread2 = new Thread(task2);

        thread1.start();
        thread2.start();
    }
}

Neste exemplo, temos duas threads (thread1 e thread2) que configuram e acessam um ID de sessão único usando ThreadLocal. Cada thread define seu próprio ID de sessão, que é então recuperado e impresso.

Exemplo 2: Contador de Threads

Outro exemplo simples é criar um contador de threads usando ThreadLocal. Esse contador pode ser útil para monitorar quantas vezes um determinado thread executa uma parte específica do código.

public class ThreadCounter {
    private static final ThreadLocal<Integer> THREAD_COUNT = ThreadLocal.withInitial(() -> 0);

    public static void increment() {
        THREAD_COUNT.set(THREAD_COUNT.get() + 1);
    }

    public static int getCount() {
        return THREAD_COUNT.get();
    }

    public static void main(String[] args) {
        Runnable task = () -> {
            for (int i = 0; i < 5; i++) {
                increment();
                System.out.println(Thread.currentThread().getName() + " Count: " + getCount());
            }
        };

        Thread thread1 = new Thread(task, "Thread-1");
        Thread thread2 = new Thread(task, "Thread-2");

        thread1.start();
        thread2.start();
    }
}

Neste exemplo, cada thread executa um loop onde incrementa seu próprio contador e imprime o valor atual. Graças ao ThreadLocal, cada thread mantém seu próprio contador independente.

Conclusão

O ThreadLocal é utilizado quando queremos isolar dados entre threads, eliminando a necessidade de sincronização em muitas situações. Ele é particularmente útil em aplicações web, onde cada requisição pode ser tratada por uma thread separada.

Se você está interessado em ver como ThreadLocal pode ser usado para implementar Multi Tenancy com banco de dados, confira nosso post detalhado sobre o assunto: Multi Tenancy com Hibernate e Spring Boot.

// Compartilhe esse Post

💫
🔥 NOVO APP

Domine o Inglês em 30 dias!

Inteligência Artificial + Repetição Espaçada • Método cientificamente comprovado

✅ Grátis para começar 🚀 Resultados rápidos
×