java - java中对象实例的线程范围

标签 java multithreading

我知道对象存储在堆空间中。更多详细信息请参见此处: https://www.hackerearth.com/practice/notes/runtime-data-areas-of-java/

在下面的代码中,对象param它的引用存储在线程堆栈中,但对象本身存储在堆中:

private void foo(Object param) { 
        ....
    } 

要问我的问题,首先我将从代码开始:

public class Thread1 implements Runnable {
Test test = new Test();

public void run() {
    test=new Test(); // This will affect other thread , the object reference is changed here
    System.out.println(test.id());
   }
    }

在上面的代码中,来自同一 Thread1 实例的所有线程都将具有相同的 test 引用(假设是变量),这意味着更改 test 的引用会影响其他线程:

  Runnable runnable=new Thread1();
    Thread thread1=new Thread(runnable);
    thread1.start();
    Thread t2=new Thread(runnable);
    thread2.start();

这里的问题是,test会存储在堆中。但线程如何访问它呢? (我认为它不会在堆栈中引用,因为在这种情况下更改线程内的值不会影响其他线程)。如果线程可以直接访问该变量(假设堆栈中没有引用)它将具有什么范围? (我的意思是它不应该局限于它自己的变量)

最佳答案

当您将 Runnable 实例传递给 Thread 构造函数时,它将将该对象存储在私有(private)字段中。当您启动线程时,您作为参数传递的可运行实例将被调用。并且线程将通过这个Runnable访问你的测试对象。(*)

如果你想知道,不同的线程如何拥有自己的测试对象副本,你应该检查 ThreadLocal .

示例:

public class Thread1 implements Runnable { 
   // each thread will have it's own copy of test object in this case
   private ThreadLocal<Test> test = new ThreadLocal<Test>();

    public void run() {
        // this line wont affect the others test instance.
        test.set( new Test() );

   }

}

(*) 为了清楚地理解这一点,您可以认为这只是将一个对象传递给另一个对象。

关于java - java中对象实例的线程范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53795593/

相关文章:

java - 最小的 Java SVG 引擎

c# - 线程停止工作

java - 使用 Spring Data 和 Hibernate 时如何正确执行后台线程?

C - exec 是否必须在多线程进程中立即跟随 fork?

java - 最后总是在方法完成之前执行?

java - 格式化 UTC 日期时间的部分秒

Java作业执行多线程与executorservice?

java - 等待并通知协调

java - Java中线程的执行顺序

java - 如何使用gradle在windows上构建jar