一、 ThreadLocal的使用

  • 正常的情况下,person对象是这两个线程共有的,即使用同一个对象,因此当一个线程修改person的name时,另一个线程的name也会改变。

public class ThreadLocal1 {
    static class Person {
        String name = "zhangsan";
    }

    volatile static Person p = new Person();

    public static void main(String[] args) {
        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(p.name);
        }).start();

        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            p.name = "lisi";
        }).start();
    }
}
  • 若使用ThreadLocal,则每一个线程都具有其独有的person对象,相互两个线程之间不影响

  • ThreadLocal的用途:声明式事务,保证同一个Connection

public class ThreadLocal2 {
    //volatile static Person p = new Person();
    static ThreadLocal<Person> tl = new ThreadLocal<>();

    public static void main(String[] args) {
        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(tl.get());
        }).start();

        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            tl.set(new Person());
        }).start();
    }

    static class Person {
        String name = "zhangsan";
    }
}

二、 源码分析

  • set
    • Thread.currentThread().ThreadLocalMap(ThreadLocal,value)
    • 设到了当前线程的ThreadLocalMap中
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            map.set(this, value);
        } else {
            createMap(t, value);
        }
    }
  • 弱引用

ThreadLocalMap里的Entry继承于WeakReference,因此Entry里保存的ThreadLocal引用是弱引用
批注 20200605 001751.jpg

    static class ThreadLocalMap {
        static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }

hhhhh