public class ThreadLocalTest {

private static ThreadLocal<Student> logs = new ThreadLocal<Student>();


public static void main(String[] args) throws InterruptedException {
// ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
public void run() {
Student student = logs.get();
if (student == null) {
student = new Student();
logs.set(student);
}
System.out.println(Thread.currentThread().getName() + "..." + student);
}
}).start();
}
}
}class Student {

}按道理来说,使用线程局部变量,每个线程都会创建一个自己独有的Student对象,但是跑出来为啥偶尔会出现(如下):
Thread-1...com.thread.Student@3fbefab0
Thread-0...com.thread.Student@3fbefab0
Thread-3...com.thread.Student@133c5982
Thread-2...com.thread.Student@3d4b7453
Thread-4...com.thread.Student@133c5982
两个线程中出现了相同的对象地址,指向同一个对象,这是为什么,是代码哪里有问题吗?求指教。

解决方案 »

  1.   


    楼主这里明显是logs.set的关系,5个线程肯定速度不一致,有的线程有延时所以在logs.get时获取其他线程的student值,不会创建新的Student
      

  2.   

    你是用线程池跑出来的问题吧,线程池线程是可以复用的
    用newthread不可能出这个问题的
      

  3.   

    System.out.println(Thread.currentThread().getName() + "..." + student)输出的@信息,是哈希值,而不是对象的地址。两个对象,哈希值相同,不一定是同一个对象
      

  4.   

    因为你用到了线程池,当线程用完以后,线程没有销毁,在接下来复用了之前的线程,所以也就复用了之前ThreadLocal对应的这个线程中的student对象
    处理的办法,就是在每个线程执行完后,对ThreadLocal中的这个student做清空处理
    ThreadLocal.remove();
      

  5.   

       ThreadLocal的正确方式应该是这样初始化数据,
     ThreadLocal<Date> threadLocal = new ThreadLocal<>(){
            @Override
            protected Date initialValue() {
                return new Date();
            }

        };