2 zhuzhu923 zhuzhu923 于 2016.01.19 20:31 提问

Java中线程的问题:明明是同一个thread对象,但是threadLocal不是同一个

package hub;
/*为啥不同线程中的ThreadLocal是互相独立的。 明明是同一个thread对象

  • 打印出来的结果 在主线程里面是var2 ,在thread线程中是var1
    */
    public class ThreadLocalUsage extends Thread {
    public User user = new User();

    public User getUser() {
    return user;
    }

    @Override
    public void run() {
    this.user.set("var1");

    while (true) {
        try {
            sleep(1000);
        } catch (InterruptedException e) {
        }
        System.out.println(this.user.get());
    }
    

    }

    public static void main(String[] args) {

    ThreadLocalUsage thread = new ThreadLocalUsage();
    thread.start();
    
    try {
        sleep(4000);
    } catch (InterruptedException e) {
    }
    
    thread.user.set("var2");
    System.out.println(thread.user.get());
    

    }
    }

class User {

private static ThreadLocal<Object> enclosure = new ThreadLocal<Object>(); // is it must be static?

public void set(Object object) {
    enclosure.set(object);
}

public Object get() {
    return enclosure.get();
}

}

上面这个代码明明是一个thread对象,怎么打印出来的threadlocal的值不一样,也就是代表不是同一个threadlocal

3个回答

wojiushiwo945you
wojiushiwo945you   Ds   Rxr 2016.01.19 21:20

ThreadLocal对象本质类似一个以线程对象为key的哈希表,它能使线程中的某个值与保存值的线程对象关联起来。
所以上述你是两个线程中分别调用了同一个ThreadLocal对象的set方法,所以get方法返回的是当前线程set的值。各个线程中的get的值对应其set的值,所以结果是:

 Thread-0:var1
main:var2
Thread-0:var1

两个线程取到的get值各是各的,当然是两个值了。

wojiushiwo945you
wojiushiwo945you   Ds   Rxr 2016.01.19 20:55

你理解错了,不是同一个thread对象,而是同一个ThreadLocal enclosure对象,即thread.user.enclosure对象。
你是两个线程中分别set到ThreadLocal对象的key是某个线程,值是线程设置的值。
你可以打印当前线程+线程设置的值,可以看到你的代码中有两个线程对象main和ThreadLocalUsage两个线程,它们存储在同一个ThreadLocal变量中。修正测试代码如下:

    public void run() {
        this.user.set("var1");
        while (true) {
            try {
                sleep(1000);
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread().getName()+":"+this.user.get());
        }

    }

    public static void main(String[] args) {
        ThreadLocalUsage thread = new ThreadLocalUsage();
        thread.start();

        try {
            sleep(4000);
        } catch (InterruptedException e) {
        }

        thread.user.set("var2");
        System.out.println(Thread.currentThread().getName()+":"+thread.user.get());

    }

测试就可以看到这是两个不同线程的值。

wojiushiwo945you
wojiushiwo945you 回复zhuzhu923: 在ThreadLocalUsage线程中的user.set("var1")是以当前线程对象为key的。get操作是取到对应线程set操作的值的。这也是ThreadLocal类的意义,就是保证每个线程都只set/get自己的数据。
2 年多之前 回复
wojiushiwo945you
wojiushiwo945you 回复毕小宝: 你此处的thread.user是取到了ThreadLocal对象,然后set操作就是以当前线程对象为key,这个var2为值存入ThreadLocal中的。
2 年多之前 回复
wojiushiwo945you
wojiushiwo945you 回复zhuzhu923: 你这个set的值是当下线程对象的,ThreadLocal本意就是每个线程拥有一份数据的。所以在对应线程中的get操作也是对应线程set时的值的。
2 年多之前 回复
zhuzhu923
zhuzhu923 ThreadLocalUsage thread = new ThreadLocalUsage(); thread.start(); 这个地方是这个线程启动的地方 thread.user.set("var2"); 这边是对这个现场的user变量设置值,这个不是应该是同一个线程对象吗
2 年多之前 回复
zhuzhu923
zhuzhu923   2016.01.21 17:14

ThreadLocalUsage thread = new ThreadLocalUsage();
thread.start();
这个地方是这个线程启动的地方
thread.user.set("var2"); 这边是对这个现场的user变量设置值,这个不是应该是同一个线程对象吗

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
不同请求获取到了相同的ThreadLocal值引起的问题
问题:两个不同的请求,在获取ThreadLocal里保存的值时,获取到了相同的值。 原因:这两个请求共用了一个线程。 1、http1.1协议中的keep-alive是默认开启的,同一个会话中,有限的请求是共用一个长连接的。 2、tomcat默认使用线程池,所以一个线程的生命周期不能对等于一个请求的生命周期,线程池中的线程是可以被复用的。 解决方案: 1、保证每次都用新
ThreadLocal的使用,保证每一个线程都有自己的共享变量。
变量的共享可以使用public static 修饰,所有的线程都使用同一个public static 变量,那如何实现每一个线程都有自己的共享变量呢,ThradLocal类就是干这个用的。 package com.wupao.controller.test; public class ThreadLocalTest { static ThreadLocal threadLocal =n
ThreadLocal 为线程绑定对象
java.lang.ThreadLocal 类,对它的调用在不同线程中有不同的结果。 1.使用场景 有些类不是线程安全的,若想在多线程下使用,我们可以为每个线程绑定一个此类的对象。 2.常用方法 T java.lang.ThreadLocal.get() 返回当前线程所持有的对象。 void java.lang.ThreadLocal.set(T value) 设置当前线程
每个线程调用的是同一个ThreadTest对象
我们接着修改ThreadDemo1,在main方法中创建四个Thread对象:   public class ThreadDemo1{   public static void main(String[] args){   newww.100ksw.comain(String[] args){   ThreadTest t = new ThreadTest();   new Thread
ThreadLocal --每个线程拥有自己独立的对象
首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。  另外,说ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象 的操作
多线程中的ThreadLocal 详解
要了解ThreadLocal,首先搞清楚ThreadLocal 是什么?是用来解决什么问题的?ThreadLocal 是线程的局部变量, 是每一个线程所单独持有的,其他线程不能对其进行访问, 通常是类中的 private static 字段,是对该字段初始值的一个拷贝,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联我们知道有时候一个对象的变量会被多个线程所访问,这时就会有线程安全
java线程访问ThreadLocal——线程间共享冲突
java线程访问ThreadLocal——线程间共享冲突 java5.0起,就有ThreadLocal支持了,ThreadLocal主要作用是线程间进行共享访问的时候创建一个副本,这样每个线程大家进行访问的时候不会产生冲突。熟悉大型游戏的朋友一定知道,大家一起打副本的意思。这里每个人都可以是一个线程,大家同样是在游行中,同样是在打副本,但是我打的怪和你打的怪不是同一个,不然我把怪打死了,你副本里
多个线程ThreadLocal中存的是什么
ThreadLocal的存储方式
权限管理系统 ThreadLocal的使用:在同一线程中获取用户信息
ThreadLocal的使用:在同一线程中获取用户信息 /*****************************************************************************************/ public class ThreadUtils implements Runnable { private static class ThreadUti
ThreadLocal防止并发线程安全 线程隔离-ThreadLocalMap
Spring使用ThreadLocal解决线程安全问题我们知道在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域。就是因为Spring对一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非线程安全状态