threadlocal

?

复制代码
整个线程的全局变量,不是程序的全局变量
线程内部的局部变量,不同的线程之间不会相互干扰

总结

  • 线程并发:在多线程并发的场景下
  • 传递数据:可以通过ThreadLocal在同一个线程,不同组件中传递公共变量
  • 线程隔离:每个线程的变量都是独立的,不会互相影响

内部结构

demo

java 复制代码
package com.jysemel.java.basic.thread.local;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

public class ThreadLocalDemo {

    private static final ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                threadLocal.set(UUID.randomUUID() + "   T1");
                try {
                    Thread.sleep(TimeUnit.SECONDS.toMillis(5));
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("T1  " + threadLocal.get());
            }
        }).start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                threadLocal.set(UUID.randomUUID() + "   T2");
                try {
                    Thread.sleep(TimeUnit.SECONDS.toMillis(5));
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("T2  " + threadLocal.get());
            }
        }).start();
    }
}

内存泄露

ini 复制代码
/**
 * 内存泄露
 */
public class ThreadLocalDemo1 {

    private static final ThreadLocal<byte []> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 100; i++) {
            executorService.execute(() -> {
                byte[] bytes = new byte[10240*20240];
                threadLocal.set(bytes);
//                threadLocal.remove();
            });
        }
        executorService.shutdown();
    }
}

结果

原因

复制代码
1、ThreadLocal对象存储在ThreadLocalMap中,当线程结束后,
ThreadLocalMap对象不会被回收,会一直保存在Thread对象中

解决内存泄露

ini 复制代码
public class ThreadLocalDemo1 {

    private static final ThreadLocal<byte []> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 100; i++) {
            executorService.execute(() -> {
                byte[] bytes = new byte[10240*20240];
                threadLocal.set(bytes);
                threadLocal.remove();
            });
        }
        executorService.shutdown();
    }
}

ThreadLocal与Synchronized的区别

  • Synchronized

    同步机制只提供了一份变量,其他线程只能等待,不能并发 多个线程之间访问资源的同步

  • ThreadLocal

    每一个线程都提供了一份变量的副本,从而实现同时访问而相不干扰 多线程中让每个线程之间的数据相互隔离

jdk8前后区别

  • jdk8之前

    ThreadLocalMap 作为 ThreadLocal 类的一个静态内部类,承担着存储线程局部变量 在这种设计模式下,无论一个进程中存在多少个不同的 ThreadLocal 实例, 它们都共享同一个 ThreadLocalMap 结构

  • jdk8之后

    使得 ThreadLocalMap 不仅是 ThreadLocal 类的静态内部类, 同时也成为了 Thread 类的一个成员变量 。 每个线程都拥有自己独立的一个 ThreadLocalMap 实例,从而实现了更细粒度的数据隔离和管理

    源码: public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { map.set(this, value); } else { createMap(t, value); } }

hash冲突如何解决

  • 开放地址法解决hash冲突
  • 当前插入的元素从冲突位置开始依次往后遍历,直到找到一个空闲位置

扩容

scss 复制代码
源码:
        private void rehash() {
            expungeStaleEntries();

            // Use lower threshold for doubling to avoid hysteresis
            if (size >= threshold - threshold / 4)
                resize();
        }
markdown 复制代码
1. 默认大小
ThreadLocalMap的初始容量是16。在创建ThreadLocalMap时,
会初始化一个长度为16的Entry数组。

2. 扩容机制
ThreadLocalMap的扩容阈值是初始容量的2/3,即当size达到阈值时,
就会进行扩容。扩容时,新容量是旧容量的2倍。
相关推荐
IT_陈寒20 小时前
为什么我的Vite热更新老是重新加载整个页面?
前端·人工智能·后端
还在忙碌的吴小二20 小时前
Harness 最佳实践:Java Spring Boot 项目落地 OpenSpec + Claude Code
java·开发语言·spring boot·后端·spring
三分恶20 小时前
支付江湖路—第一章:支付溯源——从贝壳到比特
后端
武子康20 小时前
大数据-264 实时数仓-MySQL Binlog配置详解:从原理到实践|数据恢复与主从复制实战
大数据·hadoop·后端
倾颜20 小时前
接入 MCP,不一定要先平台化:一次 AI Runtime 的实战取舍
前端·后端·mcp
wechat_Neal20 小时前
Golang的车载应用场景
开发语言·后端·golang
Moment21 小时前
AI全栈入门指南:一文搞清楚NestJs 中的 Controller 和路由
前端·javascript·后端
GetcharZp21 小时前
告别繁琐配置!这款 Go 写的 Web 服务器,凭什么让 Nginx 都不香了?
后端
IT_陈寒21 小时前
Python的asyncio把我整不会了,原来问题出在这儿
前端·人工智能·后端