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

问题描述

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

解决方案

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

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

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

解决方案二:

你理解错了,不是同一个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());

    }

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

解决方案三:

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

时间: 2024-10-07 09:05:50

java-Java中线程的问题:明明是同一个thread对象,但是threadLocal不是同一个的相关文章

java语言中线程知识点的意义和作用!

问题描述 java语言中线程知识点的意义和作用! 请问在java的学习中,线程有什么意义?老师说线程可以提高运算速度,但是线程不是同时执行多个程序呢?怎么反倒可以提高性能呢? 解决方案 因为现在的计算机有不止一个cpu(内核),多个线程可以同时使用多个cpu同时计算,同时,多线程还可以在网络.io阻塞的时候做别的事情,提高效率,所以提高了性能.

详解Java编程中线程的挂起、恢复和终止的方法_java

有时,线程的挂起是很有用的.例如,一个独立的线程可以用来显示当日的时间.如果用户不希望用时钟,线程被挂起.在任何情形下,挂起线程是很简单的,一旦挂起,重新启动线程也是一件简单的事. 挂起,终止和恢复线程机制在Java 2和早期版本中有所不同.尽管你运用Java 2的途径编写代码,你仍需了解这些操作在早期Java环境下是如何完成的.例如,你也许需要更新或维护老的代码.你也需要了解为什么Java 2会有这样的变化.因为这些原因,下面内容描述了执行线程控制的原始方法,接着是Java 2的方法. Jav

详解Java编程中线程同步以及定时启动线程的方法_java

使用wait()与notify()实现线程间协作 1. wait()与notify()/notifyAll()调用sleep()和yield()的时候锁并没有被释放,而调用wait()将释放锁.这样另一个任务(线程)可以获得当前对象的锁,从而进入它的synchronized方法中.可以通过notify()/notifyAll(),或者时间到期,从wait()中恢复执行. 只能在同步控制方法或同步块中调用wait().notify()和notifyAll().如果在非同步的方法里调用这些方法,在运

哪位大侠遇到过java虚拟机中线程这样死掉的现象,原因是什么呀

问题描述 我在项目的开发过程中遇到了一个奇怪的现象,就是在任务管理器中看java进程没有占用太多的内存,但是,其中的一个线程内存溢出了,java.lang.outofmemory java heap space 这是为什么呀 我重新调整了虚拟机的堆大小,-Xmx512m -Xms512m,但是,从任务管理器中看,当java进程占用的内存达到280多M的时候,就出现了上面的错误,这是为什么呀?通过jvisialVM看,堆内存一共占用了180多M 解决方案 线程中出现内存泄漏而已,一旦发生导致你的线

java学习日记(线程)

一.线程的概念: 线程与进程相似,是一段完成某个特定功能的代码,是程序中单个顺序的流控制:但与进程不同的是,同类的多个线程是共享一块内存空间和一组系统资源,而线程本身的数据通常只有微处理器的寄存器数据,以及一个供程序执行时使用的堆栈.所以系统在产生一个线程,或者在各个线程之间切换时,负担要比进程小的多,正因如此,线程被称为轻负荷进程(light-weight process).一个进程中可以包含多个线程. 一个线程是一个程序内部的顺序控制流. 1. 进程:每个进程都有独立的代码和数据空间(进程上

Java基础-创建Java程序中的线程池

程序|创建 线程是Java的一大特性,它可以是给定的指令序列.给定的方法中定义的变量或者一些共享数据(类一级的变量).在Java中每个线程有自己的堆栈和程序计数器(PC),其中堆栈是用来跟踪线程的上下文(上下文是当线程执行到某处时,当前的局部变量的值),而程序计数器则用来跟踪当前线程正在执行的指令. 在通常情况下,一个线程不能访问另外一个线程的堆栈变量,而且这个线程必须处于如下状态之一: 1.排队状态(Ready),在用户创建了一个线程以后,这个线程不会立即运行.当线程中的方法start()被调

Java 6中的线程优化真的有效么?

介绍 - Java 6中的线程优化 Sun.IBM.BEA和其他公司在各自实现的Java 6虚拟机上都花费了大量的精力 优化锁的管理和同步.诸如偏向锁(biased locking).锁粗化(lock coarsening).由逸出(escape)分析产生的锁省略.自适应自旋锁(adaptive spinning)这些特性,都是通过在应用程序线程之间更高效地共享数据,从而提 高并发效率.尽管这些特性都是成熟且有趣的,但是问题在于:它们的承诺真的 能实现么?在这篇由两部分组成的文章里,我将逐一探究

Java中线程封闭之ThreadLocal

在访问共享数据时通常使用同步.若不使用同步则可以将对象封闭在一个线程中达到线程安全的目的,该方法称为线程封闭(Thread Confinement).其中实现线程封闭中规范的方法是使用ThreadLocal类.线程封闭技术一种常用的使用场景是在JDBC Connection对象. public class ConnectionHelper {private final static String URL = "";private final static ThreadLocal<

总结Java中线程的状态及多线程的实现方式_java

线程的状态线程状态图: 说明: 线程共包括以下5种状态.1. 新建状态(New) : 线程对象被创建后,就进入了新建状态.例如,Thread thread = new Thread().2. 就绪状态(Runnable): 也被称为"可执行状态".线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程.例如,thread.start().处于就绪状态的线程,随时可能被CPU调度执行.3. 运行状态(Running) : 线程获取CPU权限进行执行.需要注意的是,线