ThreadLocal 详解

ThreadLocal

引用类型

强引用

我们普通的一个对象关系就是强引用。
只有当引用的对象被标记为垃圾的时候才回收。
Object o = new Object();

GC调优经历
在一次上线的项目中,发现应用频繁出现fullGC和运行一段一段时间后,出现out of memory,后面通过排查定位到,是一个类重写了finalize方法,并且有比较耗时的操作。(c++程序员习惯手动析构)。
原因:垃圾回收器在进行gc的时候会执行finalize方法,如果finalize方法操作时间过长,相对于延长了类的生命周期。

软引用

软引用非常适合作缓存。

    /**
     * 设置jvm参数-Xmx15M
     * 堆内存的最大容量为15M
     *
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        SoftReference<byte[]> softReference = new SoftReference<>(new byte[1024 * 1024 * 10]);//10M的空间
        //        byte[] bytes1 = softReference.get();   如果其他变量指向这块内存,则不会回收,相当于强引用
        System.gc();//如果内存充足,不会被回收
        TimeUnit.SECONDS.sleep(1);
        System.out.println(softReference.get());//不为null
        byte[] bytes = new byte[1024 * 1024 * 10];//10M的强引用,如果加上之前10M的软引用,则一共20M超过了堆内存的上线
        System.out.println(softReference.get());//如果内存不足,被回收,结果为null
    }

弱引用

虚引用

public class PhantomRefenerceDemo {

    public static void main(String[] args) throws InterruptedException {
        ReferenceQueue<SoftReference> queue = new ReferenceQueue<>();

        //这里虚引用指向了一个软引用
        //软引用在内存不足的时候会被自动gc
        //会加入到虚引用队列里
        PhantomReference<SoftReference> reference = new PhantomReference<>(new SoftReference<>(new byte[1024 * 1024 * 12]), queue);
        reference.get();

        List<byte[]> list = new ArrayList<>();

        new Thread(() -> {
            while (true) {
                list.add(new byte[1024 * 1024]);
                System.out.println("加入内存了");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(() -> {
            while (true) {
                Reference<? extends SoftReference> poll = queue.poll();
                if (poll != null) {
                    System.out.println("--虚引用被回收到队列了--");
                }
            }
        }).start();

        TimeUnit.SECONDS.sleep(3);

    }

}

图例

总结
强软弱四种引用,要gc的第一个条件是,对于堆内存中的对象,除了引用本身,没有其他变量对其进行引用,因为如果有其他变量对其引用,则相当于升级为强引用。
满足这个条件后,强引用是对象满足虚拟机gc的时机。
软引用是当堆内存不足的时候,会清除软引用的内存区域。
弱引用是只要进行gc则一定会清除。
虚引用和以上的用法不同,可以通过一个队列获取清除的对象,主要是用于清除直接内存。

ThreadLocal

set方法

获取到当前线程的map,将ThreadLocal对象作为key,将set的值作为vaule,存入线程的map成员变量里

threadLocal的应用

1、spring中@transaction
2、mybatis的分页
3、自己实现线程安全的一些类成员变量

posted @ 2020-11-23 19:57  刃牙  阅读(246)  评论(0编辑  收藏  举报