A classe ThreadLocal pode ser entendida como ThreadLocalVariable (variável local de thread), que fornece interfaces de acesso ou métodos como get e set. Esses métodos armazenam uma cópia independente para cada thread que utiliza a variável, portanto get sempre retorna o local da execução atual. thread O último valor definido ao chamar set. ThreadLocal<T> pode ser considerado como contendo um objeto Map<Thread,T>, contendo valores específicos para esse thread.
Resumindo, para o problema de compartilhamento de recursos multithread, o mecanismo de sincronização adota o método de “troca de tempo por espaço”, enquanto ThreadLocal adota o método de “troca de espaço por tempo”. O primeiro fornece apenas uma cópia da variável para diferentes threads enfileirarem para acesso, enquanto o último fornece uma cópia da variável para cada thread, para que possam ser acessadas ao mesmo tempo sem afetar um ao outro.
Tópico simuladoLocal
Copie o código do código da seguinte forma:
importar java.util.Collections;
importar java.util.HashMap;
importar java.util.Map;
classe pública SimpleThreadLocal<T> {
private Map<Thread, T> valueMap = Coleções
.synchronizedMap(new HashMap<Thread, T>());
public void set(T novoValor) {
valueMap.put(Thread.currentThread(), newValue); // ①A chave é o objeto do thread e o valor é uma cópia da variável deste thread
}
público T get() {
Tópico currentThread = Thread.currentThread();
T o = valueMap.get(currentThread); // ② Retorna a variável correspondente a este thread
if (o == null && !valueMap.containsKey(currentThread)) { // ③Se não existir no Mapa, coloque-o no Mapa e salve-o.
o = valorinicial();
valueMap.put(currentThread, o);
}
retornar o;
}
public void remover() {
valueMap.remove(Thread.currentThread());
}
protegido T valorinicial() {
retornar nulo;
}
}
UtilitárioThreadLocal
Copie o código do código da seguinte forma:
contagem de classe {
private SimpleThreadLocal<Integer> contagem = new SimpleThreadLocal<Integer>() {
@Substituir
valor inteiro protegido inicialValue() {
retornar 0;
}
};
aumento de número inteiro público() {
contagem.set(contagem.get() + 1);
retornar contagem.get();
}
}
classe TestThread implementa Runnable {
contagem de contagem privada;
public TestThread(Contagem) {
isto.contagem = contagem;
}
@Substituir
execução void pública() {
// TODO stub de método gerado automaticamente
for (int i = 1; i <= 3; i++) {
System.out.println(Thread.currentThread().getName() + "/t" + i
+ "th/t" + contagem.increase());
}
}
}
classe pública TestThreadLocal {
public static void main(String[] args) {
Contagem contagem = new Contagem();
Tópico t1 = novo Tópico(novo TestThread(contagem));
Tópico t2 = novo Tópico(novo TestThread(contagem));
Tópico t3 = novo Tópico(novo TestThread(contagem));
Tópico t4 = novo Tópico(novo TestThread(contagem));
t1.start();
t2.start();
t3.start();
t4.start();
}
}
O código de cópia de saída é o seguinte:
Tópico-0 1º 1
Tópico-0 2º 2
Tópico-0 3º 3
Tópico-3 1º 1
Tópico-1 1º 1
Tópico-1 2º 2
Tópico-2 1º 1
Tópico-1 3º 3
Tópico-3 2º 2
Tópico-3 3º 3
Tópico-2 2º 2
Tópico-2 3º 3