关于ThreadLocal的那些事

这篇文章(看完了再看下面的)很好地解释了ThreadLocal是什么,怎么用,是否能解决线程安全问题,非常nice。但个人认为讲解存在遗漏,进行如下示例补充:

  • InheritableThreadLocal
public class ThreadIdService {
    private static ThreadLocal<User> localUser=new InheritableThreadLocal<>();
    public static void main(String[] args) {
        User user = new User();
        user.setName("main");
        localUser.set(user);
        System.out.println("main threadUser:"+localUser.get());
        Thread t1 = new Thread() {
            @Override
            public void run() {
                System.out.println("t1User:"+localUser.get());
                localUser.get().setName("1");
                System.out.println("t1User:"+localUser.get());
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                User user2 = new User();
                user2.setName("2");
                localUser.set(user2);
                System.out.println("t2User:"+localUser.get());
            }
        };
        t1.start();
        t2.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("main threadUser:" + localUser.get());
        user.setName("main2");
    }
}

  • ThreadLocal
public class ThreadIdService {
    private static ThreadLocal<User> localUser=new ThreadLocal<>();
    public static void main(String[] args) {
        User user = new User();
        user.setName("main");
        localUser.set(user);
        System.out.println("main threadUser:"+localUser.get());
        Thread t1 = new Thread() {
            @Override
            public void run() {
                System.out.println("t1User:"+localUser.get());
                /*localUser.get().setName("1");
                System.out.println("t1User:"+localUser.get());*/
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                User user2 = new User();
                user2.setName("2");
                localUser.set(user2);
                System.out.println("t2User:"+localUser.get());
            }
        };
        t1.start();
        t2.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("main threadUser:" + localUser.get());
        user.setName("main2");
    }
}

 

  • 总结:
  1. ThreadLocal能起到线程件变量隔离的作用。
  2. InheritableThreadLocal则未必,若每个线程存放在InheritableThreadLocal的变量都采用new Object()的方式,则各线程间互不影响,否则传递的是引用,牵一发而动全身!!!
  3. InheritableThreadLocal之所以能够完成线程间变量的传递,是在new Thread()的时候对inheritableThreadLocals对像里的值进行了复制。
  4. 子线程通过继承得到的InheritableThreadLocal里的值与父线程里的InheritableThreadLocal的值具有相同的引用,如果父子线程想实现不影响各自的对象,可以重写InheritableThreadLocal的childValue方法。

 

posted @ 2020-08-31 15:40  机械公敌  阅读(160)  评论(0编辑  收藏  举报