垃圾收集和异步调用/ Future对象

时间:2015-06-08 10:48:13

标签: java multithreading

下面是一个使用Future接口进行异步调用的示例代码。我需要澄清一下get()方法。

Future<String> future = getAsyncString();
//do something ...
String msg = "";
if (validation)
    return;
else
    msg = future.get();
//do something else...
return;

将来的变量在方法中初始化,因此在方法执行后GC将很快清除该变量,因为它不再使用。 因此,如果代码进入if语句,那么JVM的状态是什么?如果没人会读回来,JVM将如何处理包装结果?它是否会影响线程池或线程执行程序?

4 个答案:

答案 0 :(得分:10)

  

如果没有人将其读回来,JVM将如何处理包装结果?

据推测,您从Future获得了Executor个对象。为了使此执行程序能够在Future中设置结果,它包含对Future的引用。换句话说,仅仅因为弹出调用堆栈时方法对对象的本地引用消失,并不意味着Future对象(在堆上)自动符合垃圾回收的条件。 / p>

异步调用未被取消或类似。执行程序将执行调用,填写结果,并可能放弃它对Future对象的引用。在点,对象变得无法访问,并且有资格进行垃圾回收。

如果您确定您的代码没有保留对Future对象的引用(即将其泄漏到// do something...部分),那么您可以确定GC(最终)收集了Future对象。 (遗嘱执行人在这里没有任何微妙的内存泄漏。)

  

[...]因此GC很快就会清除该变量。

准确地说,当弹出调用堆栈时,该变量将被丢弃。这最终将导致Future 对象无法访问,并且有资格进行垃圾回收。但是,当方法返回时,该对象通常不会立即进行垃圾收集

答案 1 :(得分:2)

  

如果没有人将其读回来,JVM将如何处理包装结果?

如果没有人(我的意思是任何程序)将要阅读它,那么GC将在垃圾收集期间处理它。但这并不意味着getAsyncString()不会被完全执行,而是在正常方法完成时它将正常完成。

答案 2 :(得分:1)

我猜。计划的未来将有一些来自线程池队列的内部引用,直到任务完成。所以在任务完成之前,它不能被gc收集。

可能存在未来和执行者之间存在额外的抽象级别,并且可以收集未来。但我确定如果提交任务,它将被运行。无论如何,指向未来的是否得到了保存。

答案 3 :(得分:0)

当您在范围内定义对它的引用或在代码中某处引用该对象时,您可以保证该对象不会被GC。

这适用于所有对象,而Future在这里没有任何区别。

因此,一旦你的方法结束,并且它的调用堆栈被清除,在将来的某个时候你的对象将有资格进行垃圾收集,但在方法的调用堆栈上存在引用它之前肯定没有。