ThreadLocal

Threadlocal的概念

Threadlocal提供了线程本地变量,它可以保证访问到的变量属于当前线程,每个线程都保存有一个变量副本,每个线程的变量都不同,Threadlocal提供了一种线程隔离,将变量与线程绑定
Threadlocal适用于多线程的情况下,可以实现传递数据,实现线程隔离

简单使用

public class Test01 {
    private static ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            threadLocal.set("mayikt");
        });
        thread.start();
        thread.join();
        System.out.println(threadLocal.get());
    }
}

Threadlocal与Synchronized区别

Synchronized和Threadlocal都可以实现多线程访问,保证线程安全问题。

  1. Synchronized当多个线程竞争到同一个资源的时候最终只能够有一个线程访问,采用时间换空间的方式,保证线程安全问题。
  2. ThreadLocal在每个线程中都有自己独立的局部变量,空间换时间,相互之间是隔离的,ThreadLocal比Synchronized高。

Threadlocal应用场景

  1. Spring事务模板类
  2. 获取httprequest

内存溢出

程序在申请内存时,没有足够的内存空间供其使用,出现out of memory ,oom溢出程序在申请内存时,没有足够的内存空间使用,一般解决,加内存

内存泄漏

指程序在申请内存后,无法释放已申请的内存空间,内存泄漏堆积会导致内存被占光,造成系统内存的浪费,导致程序运行速度减慢甚至崩溃等严重后果。

强、软、弱引用的实现区别

强引用:被引用关联的对象永远不会被垃圾回收器回收
软引用:软引用关联的对象,只有当系统内存溢出时,才会回收软引用的对象
弱引用:被弱引用关联的对象,当垃圾回收机制触发的时候就会被回收

    public static void main(String[] args) {
        UserEntity entity01 = new UserEntity("11");
        //强引用
        UserEntity entity03 = entity01;
        //弱引用
        WeakReference<UserEntity> entity02 = new WeakReference<>(entity01);
        entity01 = null;
        System.out.println(entity02.get());
        System.gc();
        System.out.println(entity02.get());
    }

Threadlocal原理分析

  1. 每个线程都有自己独立的ThreadLocalMap对象,底层时Entry对象
  2. key为当前new ThreadLocal对象,value就是Object变量值
  3. 在这里插入图片描述

Threadlocal产生内存泄漏问题

因为每个线程中都有自己独立的ThreadLocalMap对象,key为ThreadLocal,value为变量值 ,key是作为Entry对象的key,是弱引用,当ThreadLocal指向null的时候,Entry对象的key变为null,但Entry对象一直无法被垃圾回收机制回收,一直占用了系统内存,可能会造成内存泄漏的问题

如何防御Threadlocal内存泄漏问题

  1. 可以自己调用remove方法将不用的数据移除避免内存泄漏的问题
  2. 每次在做set方法的时候会清除之前key为null

Threadlocal采用弱引用而不是强引用

如果key为强引用,当我们现在将ThreadLocal的引用指向为null,但是每个线程中有自己独立ThreadLocalMap,还会一直持有该对象,所以ThreadLocal对象不会被回收,会发生ThreadLocal内存泄漏的问题。
如果key为弱引用,当我们现在将ThreadLocal的引用指向为null,Entry中的key指向为null,下次调用set方法的时候,会根据判断key为空的情况下,直接删除,有可能会发生Entry内存泄漏的问题。
不管强引用还是弱引用都是会发生内存泄漏的问题,弱引用不会发生ThreadLocal内存泄漏的问题。
ThreadLocal内存泄漏的问题,产生于ThreadLocalMap跟我们当前线程的生命周期一样,如果没有手动删除的情况下,就有可能会发生内存泄漏的问题。

ThreadLocal工具类

package com.mayikt;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * ThreadLocal 工具类
 *
 * @author :ChenYi
 * @date :2020-07-01 16:53
 */
public class ThreadLocalUtil {

    private static final ThreadLocal<Map<String, Object>> threadLocal = ThreadLocal.withInitial(() -> new HashMap<>(10));

    public static Map<String, Object> getThreadLocal() {
        return threadLocal.get();
    }

    public static <T> T get(String key) {
        return get(key, null);
    }


    public static <T> T get(String key, T defaultValue) {
        Map<String, Object> map = threadLocal.get();
        return (T) Optional.ofNullable(map.get(key)).orElse(defaultValue);
    }

    public static void set(String key, Object value) {
        Map<String, Object> map = threadLocal.get();
        map.put(key, value);
    }

    public static void set(Map<String, Object> keyValueMap) {
        Map<String, Object> map = threadLocal.get();
        map.putAll(keyValueMap);
    }

    public static void remove() {
        threadLocal.remove();
    }

    public static <T> T remove(String key) {
        Map<String, Object> map = threadLocal.get();
        return (T) map.remove(key);
    }

    public static void main(String[] args) {
        Map<String, Object> map = new HashMap<>();
        map.put("11", "1111");
        map.put("22", "2222");
        ThreadLocalUtil.set("33", "333");
        System.out.println(ThreadLocalUtil.getThreadLocal());
        ThreadLocalUtil.set(map);
        System.out.println(ThreadLocalUtil.getThreadLocal());
        Object o = ThreadLocalUtil.get("22");
        System.out.println(o);
        ThreadLocalUtil.remove("11");
        System.out.println(ThreadLocalUtil.getThreadLocal());
        ThreadLocalUtil.remove();
        System.out.println(ThreadLocalUtil.getThreadLocal());
    }
}

参考:蚂蚁课堂

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值