下面是一个使用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将如何处理包装结果?它是否会影响线程池或线程执行程序?
答案 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在这里没有任何区别。
因此,一旦你的方法结束,并且它的调用堆栈被清除,在将来的某个时候你的对象将有资格进行垃圾收集,但在方法的调用堆栈上存在引用它之前肯定没有。