[ThreadLocal] Cenários e exemplos de uso de ThreadLocal

ThreadLocal é uma medida importante para fechamento de thread, e DateTimeContextHolder e RequestContextHolder no Spring também são úteis.

Cenários de uso de ThreadLocal

Cenário 1: isolamento de objeto - o thread precisa de um objeto exclusivo (como SimpleDateFormat)

Threads compartilham exclusivamente uma classe de ferramenta de objeto, como Random e DateFormat, geralmente por razões de segurança e eficiência de thread.

Para o cenário de objeto exclusivo de thread, o método principal é substituir o método innitialValue ().

public class RrightWaySimpleDateFormater {
    
    
    public static ExecutorService threadPool = Executors.newFixedThreadPool(10);
    /**
     * 定义ThreadLocal变量--JDK8实现形式
     */
    private static final ThreadLocal<SimpleDateFormat> dateThreadSafe = ThreadLocal.withInitial(
        () -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
   );

    public static void main(String[] args) throws InterruptedException {
    
    
        for (int i = 0; i < 1000; i++) {
    
    
            int finalI = i;
            threadPool.submit(() -> {
    
    
                System.out.println(new RrightWaySimpleDateFormater().date(finalI));
            });
        }
        threadPool.shutdown();
    }

    public String date(int seconds) {
    
    
        return dateThreadSafe.get().format(new Date(1000 * seconds));
    }
}

JDK7 e formulários de implementação anteriores

private static final ThreadLocal<SimpleDateFormat> dateThreadSafe2 = new ThreadLocal<SimpleDateFormat>() {
    
    
     @Override
     protected SimpleDateFormat initialValue() {
    
    
         return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     }
};

Deve-se observar que ThreadLocal geralmente não é adequado para pools de threads.

Ali java manual:
[Obrigatório] SimpleDateFormat é uma classe thread-insegura e geralmente não deve ser definida como uma variável estática. Se for definido como estático, deve ser bloqueado ou usar a classe de ferramenta DateUtils. O tratamento acima também é recomendado.
O JDK8 recomenda o uso de DateTimeFormatter em vez de SimpleDateFormat, Instant em vez de Date e LocalDateTime em vez de Calendar.

Cenário 2: Transferência de objeto

Threads precisam salvar variáveis ​​globais para que diferentes métodos possam ser usados ​​diretamente, sem a necessidade de passar dados camada por camada como parâmetros.

ThreadLocal pode ser usado para salvar algumas informações de negócios, como informações de autoridade do usuário, nome do usuário, ID do usuário, número do telefone celular e assim por diante. As informações de negócios são as mesmas no mesmo segmento, mas o conteúdo em diferentes segmentos é diferente. A ênfase está no compartilhamento entre métodos diferentes dentro da mesma solicitação (dentro do mesmo encadeamento).

O mapa também pode armazenar as informações comerciais acima. Quando vários threads trabalham ao mesmo tempo, a segurança dos threads precisa ser garantida. Por exemplo, usar uma variável estática ConcurrentHashMap, usar o ID do thread como a chave e armazenar os dados de negócios como o Valor, pode atingir o isolamento entre os threads, mas ainda tem um impacto no desempenho.

public class RightWayThreadLocalUse {
    
    
    public static void main(String[] args) {
    
    
        new ServiceImpl1().service(new UserInfo("lzp", "1234567890"));
    }
}

/**
 * 接收数据
 */
class ServiceImpl1 {
    
    
    public void service(UserInfo userInfo) {
    
    
        UserInfoHolder.holder.set(userInfo);
        new ServiceImpl2().service();
    }
}

/**
 * 处理数据1
 */
class ServiceImpl2 {
    
    
    public void service() {
    
    
        System.out.println("客户名:" + UserInfoHolder.holder.get().cltNam);
        new ServiceImpl3().service();
    }
}

/**
 * 处理数据2
 */
class ServiceImpl3 {
    
    
    public void service() {
    
    
        System.out.println("客户号:" + UserInfoHolder.holder.get().cltNbr);
        // 此时使用完ThreadLocal,回收该ThreadLocal
        UserInfoHolder.holder.remove();
    }
}

class UserInfoHolder {
    
    
    public static ThreadLocal<UserInfo> holder = new ThreadLocal<>();
}

class UserInfo {
    
    
    String cltNam;
    String cltNbr;

    public UserInfo(String cltNam, String cltNbr) {
    
    
        this.cltNam = cltNam;
        this.cltNbr = cltNbr;
    }
}

Vantagens do ThreadLocal

(1) A variável ThreadLocal é privada para o thread, portanto, o thread é seguro e não precisa ser bloqueado, portanto, não há bloqueio e a eficiência de execução é aprimorada.
(2) Use a memória com eficiência e economize overhead. Para o cenário de uso do pool de threads, é necessário apenas que cada thread de trabalho tenha uma instância ThreadLocal do objeto.
(3) Para o cenário de cadeia de chamadas, evite a transmissão repetida de objetos, usados ​​para armazenar informações de negócios, e obter desacoplamento de código.

Acho que você gosta

Origin blog.csdn.net/LIZHONGPING00/article/details/105211631
Recomendado
Clasificación