说我做以下...
//MyRunnable是我声明的一个类,它实现了Runnable。
MyRunnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
r = null;
像我在上面的代码片段中那样将 r 设置为 null 有什么影响?
说我做以下...
//MyRunnable是我声明的一个类,它实现了Runnable。
MyRunnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
r = null;
像我在上面的代码片段中那样将 r 设置为 null 有什么影响?
让我通过数字向您解释:
1- 在
MyRunnable r = new MyRunnable();
MyRunnable
您正在创建主要实现Runnable
接口的类的新实例:
2- 在
Thread t = new Thread(r);
您正在创建一个新线程并按值传递引用 r 指向的对象:
3- 在
r = null;
您正在删除 r 引用和MyRunnable
对象之间的链接,Threadt
正在使用该链接来运行线程:
没有影响。
线程已经开始了。无论如何,线程对象将保留引用,因此它不会被垃圾收集,直到t
这样做。
没有。
变量r
不是对象本身;MyRunnable
它只是代码块中对该对象的引用。
最初,您创建一个新MyRunnable
对象。然后,您“为其命名”/将其分配给变量r
。然后将它传递给Thread
构造函数(使用变量来描述您正在谈论的对象)。在该构造函数中,它几乎肯定会被分配给其他引用(在我使用的 JDK 中,它是一个名为 的字段target
)。
稍后,您将引用重新指向r
另一个对象 - 在本例中为null
对象。这对它用来指向它的对象没有任何影响,只是引用。同样,它对指向同一对象的其他引用没有任何影响。
所以Thread.target
引用仍然指向MyRunnable
你最初创建的同一个对象,从线程的角度来看,没有任何改变。
唯一的潜在区别是您的(外部)代码片段不再引用它创建的对象。因此,后面的代码将无法调用该对象上的任何方法,或将其作为方法参数传递等。(这不应该是一个问题 - 或令人惊讶 - 鉴于您故意取消了对该对象的唯一引用! )
如果没有任何东西持有对特定对象的引用,那么垃圾收集器将在下一次运行时认为该对象不可达,并收集它。不过,您很少需要担心这一点,因为如果您没有对该对象的引用,那么无论如何您将无法对它做任何事情(GC 背后的整个原理)。
在这种情况下,MyRunnable
不会被 GCed,因为Thread
仍然持有对它的引用。
也就是说,如果构造函数的行为不同并且不存储引用,因为它不需要引用(也许它只是使用toString()
表示),那么该对象将被视为不可访问,并将被收集。在这两种情况下,垃圾收集器都会做正确的事情——当且仅当没有东西再引用它时才收集一个对象——而您无需担心或知道代码中的这一点。