Java中对象实例的线程作用域

时间:2018-12-15 17:31:10

标签: 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的相同引用(假设为变量),这意味着更改测试的引用将影响其他线程:< / p>

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

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

1 个答案:

答案 0 :(得分:1)

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

如果您想知道不同的线程如何拥有自己的Test对象副本,则应检查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() );

   }

}

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