您当前的位置: 首页 > 

cuiyaonan2000

暂无认证

  • 2浏览

    0关注

    248博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

ThreadLocal&&Reference

cuiyaonan2000 发布时间:2022-05-17 16:16:34 ,浏览量:2

序言

目前ThreadLocal使用场景最多的就是多数据源的切换了.我们在使用ThreadLocal在不同线程之间切换数据源的时候要其实有很多知识点需要注意cuiyaonan2000@163.com

线程的状态

线程入门的知识,但是在后续的设计中会应用到cuiyaonan2000@163.com

系统线程的状态
  • 新建(NEW)
  • 就绪(RUNNABLE)
  • 运行(RUNNING)
  • 阻塞(BLOCKING): sleep,wating,blocking
  • 死亡(DEAD)
Java线程状态

Java的线程状态跟系统的差不多,同时new Thread()对象可以通过getState()查看到JDK给你的线程提供的几种状态cuiyaonan2000@163.com

人工翻译一下(Java貌似就多了个超时状态):

  • 新建: 一个线程尚未开始的时候是这个状态
  • 可运行状态: 一个线程在JVM中运行是的状态(为什么不是Running)
  • 阻塞: 一个线程阻塞等待一个监控锁的时候在此状态
  • 等待状态
  • 超时状态
  • 终止状态

其实我要重温这个的目的是想确定,一个线程会不会在阻塞的时候执行其它的任务,如果是这样ThreadLocal就你妹的没用了cuiyaonan2000@163.com

Reference

Java 提供了如下的抽象类

  1. java.lang.ref.Reference
  2. java.lang.ref.SoftReference
  3. java.lang.ref.WeakReference
  4. java.lang.ref.PhantomReference
强引用

强引用的对象是不可以GC回收的,不可以随意回收具有强引用的对象来解决内存不足的问题。------除非对象没有引用指向才会被GC回收.否则不在GC的范围内

把一个对象赋给一个引用类型变量,则为强引用。

在Java中,强引用是一种默认的状态,除非JVM虚拟机停止工作。

String email = "cuiyaonan2000@163.com";

软引用

软引用的意思是只有在内存不足的情况下,被引用的对象才会被回收。

可以通过java.lang.ref.SoftReference使用软应用.该类有2个构造行数

    /**
     * Creates a new soft reference that refers to the given object.  The new
     * reference is not registered with any queue.
     *
     * @param referent object the new soft reference will refer to
     */
    public SoftReference(T referent) {
        super(referent);
        this.timestamp = clock;
    }


    /**
     * Creates a new soft reference that refers to the given object and is
     * registered with the given queue.
     *
     * @param referent object the new soft reference will refer to
     * @param q the queue with which the reference is to be registered,
     *          or null if registration is not required
     *
     */
    public SoftReference(T referent, ReferenceQueue k, Object v) {
                super(k);
                value = v;
            }
        }


    private Entry[] table;

}

再看下set方法,key就是ThreadLocal 由它的hashcode来计算出数组的下标,来存放最终的value.

这里ThreadLocal是我们代码声明的,是固定的,它所保存的值是存储在不同线程中的,相当于ThreadLocal是一把钥匙,用来从不同的线程中取出自己放置的值cuiyaonan2000@163.com

这样子就满足了不同线程的ThreadLocal钥匙会取出不同的值

private void set(ThreadLocal key, Object value) {

            // We don't use a fast path as with get() because it is at
            // least as common to use set() to create new entries as
            // it is to replace existing ones, in which case, a fast
            // path would fail more often than not.

            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);

            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                ThreadLocal k = e.get();

                if (k == key) {
                    e.value = value;
                    return;
                }

                if (k == null) {
                    replaceStaleEntry(key, value, i);
                    return;
                }
            }

            tab[i] = new Entry(key, value);
            int sz = ++size;
            if (!cleanSomeSlots(i, sz) && sz >= threshold)
                rehash();
        }

ThreadLocal内存溢出的原因

因为ThreadLocalMap 是使用ThreadLocal作为Key ,同时ThreadLocalMap跟Thread的声明周期一样长(这是废话因为,ThreadLocalMap是Thread的一个属性cuiyaonan2000@163.com),所以ThreadLocalMap会一直保持对ThreadLocal的引用,根据java的可达分析原则,ThreadLocalMap中的value不会被清理, 当然当Thread关闭的时候可以被清理,但是我们现在都是用的线程池,所以会造成内存溢出.

关注
打赏
1638267374
查看更多评论
立即登录/注册

微信扫码登录

0.5631s