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倍。
相关推荐
爱勇宝13 小时前
2026一人公司生存指南:用AI大模型,90天跑出你的第一条现金流
前端·后端·架构
golang学习记14 小时前
Go 并发编程:原子操作(Atomics)完全指南
后端
哈里谢顿14 小时前
`127.0.0.1` 和 `0.0.0.0` 有何区别?通过验证 demo来展示
后端
树獭叔叔14 小时前
08-大模型后训练的指令微调SFT:LoRA让大模型微调成本降低99%
后端·aigc·openai
苏三说技术14 小时前
我终于遇到一台真正懂程序员的显示器!
后端
Re_zero15 小时前
线上日志被清空?这段仅10行的 IO 代码里竟然藏着3个毒瘤
java·后端
花落人散处15 小时前
流式输出——解决 HITL 难题 (SpringAIAlibaba)
后端
BingoGo16 小时前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack17 小时前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
Victor35617 小时前
MongoDB(18)如何向MongoDB集合中插入文档?
后端