浅谈ThreadLocal的理解

浅谈ThreadLocal的理解


引用类型介绍

说到ThreadLocal的话,就不得不提及到几种引用类型:
强、软、弱、虚

强引用
// 强引用,就算发生gc,当对象还被引用这就不会被回收,当发生内存溢出直接爆出异常
// 新增启动参数
// -Xms1m -Xmx1m -XX:+HeapDumpOnOutOfMemoryError    会出现一下异常
// Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
public static void main(String[] args) {
    byte[] bytes = new byte[1024 * 10214];
    System.gc();
    System.out.println(bytes);
}
复制代码
软引用
// 软引用:当内存空间不足时,会被回收到空间足够则就不回收,

// 配置启动参数:-Xms3m -Xmx3m -XX:+HeapDumpOnOutOfMemoryError
// ①调整启动参数:到5M是,会存在部分
// 当去掉启动参数,则输出全部有值

// 声明集合类存储软应用类
private static List<SoftReference> list = new ArrayList<>();

public static void softReference() {
    for (int i = 0; i < 10; i++) {
        byte[] bytes = new byte[1024 * 1024];
        // 对于softReference是强引用,而softReference的bytes则为软引用
        SoftReference<byte[]> softReference的bytes则为软引用 = new SoftReference<byte[]>(bytes);
        list.add(softReference);
    }
    // 主动触发gc
    System.gc();
    list.stream().forEach(e -> System.out.println(e.get()));
}
复制代码
运行结果:内存为3M时
    null
    null
    null
    null
    null
    null
    null
    null
    null
    [B@2dda6444
    
 运行结果:内存为5M时   
    null
    null
    null
    null
    null
    null
    [B@79fc0f2f
    [B@50040f0c
    [B@2dda6444
    [B@5e9f23b4
   
复制代码

弱引用:

// 启动参数:-Xms5m -Xmx5m -XX:+HeapDumpOnOutOfMemoryError
// 执行结果可以看出在添加到list的过程中实际上出现发生了gc,
// 手动执行gc之后list中所有的WeakReference引用都被释放
private static List<WeakReference> list = new ArrayList<>();

public static void weakReference() {
    for (int i = 0; i < 5; i++) {
        byte[] bytes = new byte[1024 * 1024];
        WeakReference<byte[]> ref = new WeakReference<>(bytes);
        list.add(ref);
    }
    list.stream().forEach(e -> System.out.println(e.get()));
    System.gc();
    System.out.println("=============gc之后===============");
    list.stream().forEach(e -> System.out.println(e.get()));
}

复制代码
运行结果:
null
null
null
[B@79fc0f2f
[B@50040f0c
=============gc之后===============
null
null
null
null
null
   
复制代码

虚引用:

// 虚引用通常和ReferenceQueue一起连用,所以引入ReferenceQueue类
// 虚引用无论gc是否发生,都不能获取到对象数据
// 原因①:PhantomReference在继承Reference类是只有一个get方法的实现,返回的是null
// 原因①:因为虚引用是使用的计算机的直接内存,jvm不能跨空间获取
// 涉及用户态和内核态的切换问题,感兴趣的可以自己去学习一下
public static void phantomReference() {
    byte[] bytes = new byte[1024 * 1024];
    ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
    PhantomReference sf = new PhantomReference<>(bytes, referenceQueue);
    System.out.println("gc前:" + sf.get());
    System.gc();
    System.out.println("gc后:" + sf.get());
}

复制代码
运行结果:
gc前:null
gc后:null
   
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享