zoukankan      html  css  js  c++  java
  • ThreadLocal类学习笔记

    这个类在java1.2中就出现了,线程独有的变量(每个线程都有一份变量),使用它的好处之一就是可以少传许多参数。

    在哪里用到它呢?有连接池的地方就有它的身影,连接池包括数据库连接池,网络连接池等。

    import java.util.UUID;
    
    class Factory {
        static ThreadLocal<String> connection=new ThreadLocal<>();
        static String getConnection() {
            String s=connection.get();
            if (s == null) {
                connection.set(UUID.randomUUID().toString());
            }
            return connection.get();
        }
    }
    public class TestThreadLocal {
        static void f() {
            String s = Factory.getConnection();
            System.out.println("f :" + s);
            g();
        }
        static void g() {
            String s = Factory.getConnection();
            System.out.println("g :" + s);
        }
        public static void main(String[] args) {
            new Thread(() -> f()).start();
            new Thread(() -> f()).start();
        }
    }

    输出结果:

    f :6c71fba2-8fd6-4de9-88f9-69023290e213
    f :c315c241-b379-446d-8159-dc758f020a80
    g :c315c241-b379-446d-8159-dc758f020a80
    g :6c71fba2-8fd6-4de9-88f9-69023290e213

    ThreadLocal<String>connection这个变量其实就是一个马甲,它是唯一的一份(因为它是静态的呀)。这唯一的一份就相当于一个线程大管家,它负责去访问当前线程。请看ThreadLocal#get方法

    public T get() {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null) {
                ThreadLocalMap.Entry e = map.getEntry(this);
                if (e != null) {
                    @SuppressWarnings("unchecked")
                    T result = (T)e.value;
                    return result;
                }
            }
            return setInitialValue();
        }

    第一步,它会去获取当前线程t

    第二步,通过当前线程t获取ThreadLocalMap对象map

    第三步,如果没有map,那就给当前线程new出来一个并赋上初值(通过setInitialValue来实现);如果已经存在,那就读取之。

    ThreadLocalMap这个类是一个内部静态类,全名是:ThreadLocal.ThreadLocalMap,其内部元素的键就是this(也就是ThreadLocal实例,即上例中的connection变量),值是Object类型的实例。

        Entry(ThreadLocal<?> k, Object v)

    Thread这个类大名鼎鼎,它内部有一个成员变量:

        ThreadLocal.ThreadLocalMap threadLocals = null;

    上例中,线程1和线程2各有一份ThreadLocalMap成员变量threadLocals,这两个threadLocals中都有同一份键:connection,但是它们的值不是同一份。

    每一个线程都维持一份ThreadLocalMap threadLocals,ThreadLocal这个大管家负责访问当前线程对象的threadLocals变量

    可见,ThreadLocal机制是纯java代码,没有底层实现,我们自己也是可以实现的,这是一种巧妙地机制。

    ThreadLocal和ThreadLocalMap在同一个文件里面并且ThreadLocalMap是ThreadLocal的静态内部类,然后Thread又有ThreadLocalMap的成员变量,最后ThreadLocal变量作为一个大管家去访问ThreadLocalMap。这个API设计的真是合理,就该这么整啊!实现起来简简单单,却带来许多便利。

  • 相关阅读:
    用C#实现DES加密解密解决URL参数明文的问题
    C#数据集合分页处理
    图像处理中的hard negative mining(难例挖掘)
    目标检测最近
    Object Detection(目标检测神文)
    ssm框架整合基本步骤练习总结
    Android 数据存储之 SQLite数据库存储
    android内部存储与外部存储理解
    Android数据存储之SharePreference和内部存储
    AlertDialog和自定义对话框
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/5426438.html
Copyright © 2011-2022 走看看