7

说我做以下...

//MyRunnable是我声明的一个类,它实现了Runnable。

MyRunnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();

r = null;

像我在上面的代码片段中那样将 r 设置为 null 有什么影响?

4

3 回答 3

8

让我通过数字向您解释:

1- 在

MyRunnable r = new MyRunnable();

MyRunnable您正在创建主要实现Runnable接口的类的新实例:

在此处输入图像描述

2- 在

Thread t = new Thread(r);

您正在创建一个新线程并按传递引用 r 指向的对象:

在此处输入图像描述

3- 在

r = null;

您正在删除 r 引用和MyRunnable对象之间的链接,Threadt正在使用该链接来运行线程:

在此处输入图像描述

于 2012-06-13T09:33:20.090 回答
6

没有影响。

线程已经开始了。无论如何,线程对象将保留引用,因此它不会被垃圾收集,直到t这样做。

于 2012-06-13T09:13:59.870 回答
3

没有。

变量r不是对象本身MyRunnable它只是代码块中对该对象的引用。

最初,您创建一个新MyRunnable对象。然后,您“为其命名”/将其分配给变量r。然后将它传递给Thread构造函数(使用变量来描述您正在谈论的对象)。在该构造函数中,它几乎肯定会被分配给其他引用(在我使用的 JDK 中,它是一个名为 的字段target)。

稍后,您将引用重新指向r另一个对象 - 在本例中为null对象。这对它用来指向它的对象没有任何影响,只是引用。同样,它对指向同一对象的其他引用没有任何影响。

所以Thread.target引用仍然指向MyRunnable你最初创建的同一个对象,从线程的角度来看,没有任何改变。

唯一的潜在区别是您的(外部)代码片段不再引用它创建的对象。因此,后面的代码将无法调用该对象上的任何方法,或将其作为方法参数传递等。(这不应该是一个问题 - 或令人惊讶 - 鉴于您故意取消了对该对象的唯一引用! )


如果没有任何东西持有对特定对象的引用,那么垃圾收集器将在下一次运行时认为该对象不可达,并收集它。不过,您很少需要担心这一点,因为如果您没有对该对象的引用,那么无论如何您将无法对它做任何事情(GC 背后的整个原理)。

在这种情况下,MyRunnable不会被 GCed,因为Thread仍然持有对它的引用。

也就是说,如果构造函数的行为不同并且不存储引用,因为它不需要引用(也许它只是使用toString()表示),那么该对象将被视为不可访问,并将被收集。在这两种情况下,垃圾收集器都会做正确的事情——当且仅当没有东西再引用它时才收集一个对象——而您无需担心或知道代码中的这一点。

于 2012-06-13T09:24:14.560 回答