V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zhongxigeng
V2EX  ›  Java

ThreadLocal 和 Thread 局部变量的区别? ThreadLocal 在什么场景下,用它比用 Thread 的局部变量好?

  •  
  •   zhongxigeng · 2016-07-21 17:11:49 +08:00 · 5729 次点击
    这是一个创建于 3049 天前的主题,其中的信息可能已经有所发展或是发生改变。

    分析:

    1. ThreadLocal :提供线程内的局部变量,这种变量在线程的生命周期内起作用
    2. Thread 局部变量:线程内部的变量

    二者有啥区别,怎么看 都觉得 二者一摸一样,请大家分析分析 ThreadLocal 在什么场景下,用它比用 Thread 的局部变量好。

    自写的测试代码:

    public class ThreadLocalTest {
    
        private static final ThreadLocal<Integer> value = new ThreadLocal<Integer>() {
            @Override
            protected Integer initialValue() {
                return 0;
            }
        };
    
        public static void main(String[] args) {
            for (int i = 0; i < 5; i++) {
                new Thread(new MyThread(i + "")).start();
            }
        }
    
        static class MyThread implements Runnable {
            private String index;
    
            public MyThread(String index) {
                this.index = index;
            }
    
            //局部变量
            private Integer num = 0;
    
            public void run() {
                System.out.println("线程" + index + "的初始 num:" + num);
                System.out.println("线程" + index + "的初始 value:" + value.get());
                for (int i = 0; i < 10; i++) {
                    num += i;
                    value.set(value.get() + i);
                }
                System.out.println("线程" + index + "的累加 num:" + num);
                System.out.println("线程" + index + "的累加 value:" + value.get());
            }
        }
    }
    
    8 条回复    2016-07-22 15:06:49 +08:00
    zhongxigeng
        1
    zhongxigeng  
    OP
       2016-07-21 17:29:18 +08:00
    已自己找到了不同点,问的问题很 2 ,见谅~~
    ```java
    public static void main(String[] args) {

    MyThread myThread = new MyThread("oo");
    new Thread(myThread,"1").start();
    new Thread(myThread,"2").start();
    }
    static class MyThread implements Runnable {
    private String index;

    public MyThread(String index) {
    this.index = index;
    }

    //局部变量
    private Integer num = 0;

    public void run() {
    System.out.println("线程" + Thread.currentThread().getName() +index+ "的初始 num:" + num);
    System.out.println("线程" + Thread.currentThread().getName()+index + "的初始 value:" + value.get());
    for (int i = 0; i < 10; i++) {
    num += i;
    value.set(value.get() + i);
    }
    System.out.println("线程" + Thread.currentThread().getName() +index + "的累加 num:" + num);
    System.out.println("线程" + Thread.currentThread().getName() +index + "的累加 value:" + value.get());
    }
    }
    ```

    结果:
    ```
    线程 2oo 的初始 num:0
    线程 1oo 的初始 num:0
    线程 2oo 的初始 value:0
    线程 1oo 的初始 value:0
    线程 2oo 的累加 num:45
    线程 1oo 的累加 num:90
    线程 1oo 的累加 value:45
    线程 2oo 的累加 value:45
    ```

    结论:自定义私有局部变量 线程不安全,当上述情况时
    8bit
        2
    8bit  
       2016-07-21 17:29:54 +08:00 via Android
    threadlocal 用来处理全局变量的共享问题,局部变量在一定范围内就是线程封闭的呀
    aabbccli
        3
    aabbccli  
       2016-07-21 20:01:28 +08:00
    你可以把它看作是一个全局的 MAP,KEY 为线程 ID , VALUE 为对应线程设置的值
    hinkal
        4
    hinkal  
       2016-07-21 20:10:55 +08:00 via Android
    我也思考过这个问题,应用场景区别就是,使用线程局部存储后,可以对所有线程都调用同样的变量名啊
    lululau
        5
    lululau  
       2016-07-21 20:16:22 +08:00 via iPhone
    第二个只是对象的私有实例变量好吗,和线程有啥关系
    hinkal
        6
    hinkal  
       2016-07-21 20:21:31 +08:00 via Android
    补充,刚才回答以为是 win32API 请自动忽略...
    Override
        7
    Override  
       2016-07-21 21:26:36 +08:00 via Android
    我仿佛又听到有人在背后偷偷 @我
    wangyunbin1989
        8
    wangyunbin1989  
       2016-07-22 15:06:49 +08:00
    ThreadLocal 类似于一个线程中的全局变量
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1374 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 23:49 · PVG 07:49 · LAX 15:49 · JFK 18:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.