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倍。
相关推荐
神奇小汤圆2 小时前
告别手写HTTP请求!Spring Feign 调用原理深度拆解:从源码到实战,一篇搞懂
后端
布列瑟农的星空2 小时前
前端都能看懂的Rust入门教程(三)——控制流语句
前端·后端·rust
汤姆yu2 小时前
基于springboot的尿毒症健康管理系统
java·spring boot·后端
暮色妖娆丶2 小时前
Spring 源码分析 单例 Bean 的创建过程
spring boot·后端·spring
野犬寒鸦2 小时前
从零起步学习JVM || 第一章:类加载器与双亲委派机制模型详解
java·jvm·数据库·后端·学习
Java编程爱好者2 小时前
Seata实现分布式事务:大白话全剖析(核心讲透AT模式)
后端
神奇小汤圆2 小时前
比MySQL快800倍的数据库:ClickHouse的性能秘密
后端
小小张说故事3 小时前
BeautifulSoup:Python网页解析的优雅利器
后端·爬虫·python
怒放吧德德3 小时前
后端 Mock 实战:Spring Boot 3 实现入站 & 出站接口模拟
java·后端·设计