A ThreadLocal do Java é usada para criar variáveis locais de thread. Sabemos que todos os threads de um objeto compartilham suas variáveis, tornando a variável não segura para threads. Podemos usar sincronização para garantir a segurança do thread, mas se quisermos evitar a sincronização, podemos usar variáveis ThreadLocal
.
ThreadLocal do Java
Cada thread tem sua própria variável
ThreadLocal
e pode usar os métodos get() e set() para obter o valor padrão ou alterar o valor local para o thread. As instâncias de ThreadLocal são geralmente campos estáticos privados em classes que desejam associar estado a um thread.
Exemplo de ThreadLocal em Java
Aqui está um pequeno exemplo mostrando o uso de ThreadLocal em um programa Java e provando que cada thread tem sua própria cópia da variável ThreadLocal. ThreadLocalExample.java
package com.journaldev.threads;
import java.text.SimpleDateFormat;
import java.util.Random;
public class ThreadLocalExample implements Runnable{
// SimpleDateFormat não é thread-safe, então forneça um para cada thread
private static final ThreadLocal formatter = new ThreadLocal(){
@Override
protected SimpleDateFormat initialValue()
{
return new SimpleDateFormat("yyyyMMdd HHmm");
}
};
public static void main(String[] args) throws InterruptedException {
ThreadLocalExample obj = new ThreadLocalExample();
for(int i=0 ; i<10; i++){
Thread t = new Thread(obj, ""+i);
Thread.sleep(new Random().nextInt(1000));
t.start();
}
}
@Override
public void run() {
System.out.println("Thread Name= "+Thread.currentThread().getName()+" default Formatter = "+formatter.get().toPattern());
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
// o padrão do formatador é alterado aqui por thread, mas não será refletido em outros threads
formatter.set(new SimpleDateFormat());
System.out.println("Thread Name= "+Thread.currentThread().getName()+" formatter = "+formatter.get().toPattern());
}
}
A saída do programa de exemplo Java ThreadLocal acima é:
Thread Name= 0 default Formatter = yyyyMMdd HHmm
Thread Name= 1 default Formatter = yyyyMMdd HHmm
Thread Name= 0 formatter = M/d/yy h:mm a
Thread Name= 2 default Formatter = yyyyMMdd HHmm
Thread Name= 1 formatter = M/d/yy h:mm a
Thread Name= 3 default Formatter = yyyyMMdd HHmm
Thread Name= 4 default Formatter = yyyyMMdd HHmm
Thread Name= 4 formatter = M/d/yy h:mm a
Thread Name= 5 default Formatter = yyyyMMdd HHmm
Thread Name= 2 formatter = M/d/yy h:mm a
Thread Name= 3 formatter = M/d/yy h:mm a
Thread Name= 6 default Formatter = yyyyMMdd HHmm
Thread Name= 5 formatter = M/d/yy h:mm a
Thread Name= 6 formatter = M/d/yy h:mm a
Thread Name= 7 default Formatter = yyyyMMdd HHmm
Thread Name= 8 default Formatter = yyyyMMdd HHmm
Thread Name= 8 formatter = M/d/yy h:mm a
Thread Name= 7 formatter = M/d/yy h:mm a
Thread Name= 9 default Formatter = yyyyMMdd HHmm
Thread Name= 9 formatter = M/d/yy h:mm a
Como você pode ver a partir da saída, a Thread-0 alterou o valor do formatador, mas o formatador padrão da Thread-2 ainda é o mesmo que o valor inicializado. Você pode ver o mesmo padrão para outras threads também. Atualização: A classe ThreadLocal foi estendida no Java 8 com um novo método withInitial()
que recebe a interface funcional Supplier como argumento. Portanto, podemos usar expressões lambda para criar facilmente a instância ThreadLocal. Por exemplo, a variável ThreadLocal do formatador acima pode ser definida em uma linha da seguinte forma:
private static final ThreadLocal<SimpleDateFormat> formatter =
ThreadLocal.<SimpleDateFormat>withInitial
(() -> {return new SimpleDateFormat("yyyyMMdd HHmm");});
Se você é novo nas funcionalidades do Java 8, por favor, confira Recursos do Java 8 e Interfaces Funcionais do Java 8. Isso é tudo para o ThreadLocal na programação Java. Referência: Doc API
Source:
https://www.digitalocean.com/community/tutorials/java-threadlocal-example