2015-06-08 37 views
7

下面是使用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將如何處理包裝結果?它是否會影響線程池或線程執行程序?

+3

變量不會被GC清除。 GC清除不再被任何變量引用的對象。請注意,變量不是一個對象;一個變量是一個對象的*引用*。 – Jesper

+0

是的,代碼表明未來的實例將只用於方法 – AntJavaDev

+0

爲什麼你在'getAsyncString()'之後驗證而不是之前? –

回答

2

JVM如何處理包裝結果,以防無人讀取它?

如果沒有人(我的意思是任何程序)要讀取它,那麼GC會在垃圾回收期間處理它。但是這並不意味着getAsyncString()將不會完全執行,而是會在正常方法完成時正常完成。

+0

這是我想確認的答案,我們如何確認?我應該在運行時檢查內存空間嗎? – AntJavaDev

+0

你想確認什麼,那是垃圾收集還是執行完成? –

+0

不會執行,因爲調用該方法時,問題是包裝結果會發生什麼情況,以防代碼永遠無法到達future.get()?它會創建一個內存泄漏或什麼? – AntJavaDev

10

JVM如何處理包裝結果,以防無人讀取它?

想必您從Executor得到Future對象。對於該執行者可以在Future中設置結果,它可以參考Future。換句話說,僅僅因爲對象的方法本地引用隨着調用堆棧彈出而消失,並不意味着Future對象(位於堆上)自動符合垃圾回收的條件。

異步調用未取消或類似的東西。執行者將執行呼叫,填寫結果,並且可能推斷它對Future對象的引用。在這個指向的對象變得無法訪問並有資格進行垃圾回收。

如果你確信你的代碼不保留到Future對象的引用(即泄露其在// do something...部分),那麼你可以肯定的是,Future對象是(最終)由GC收集。 (執行者在這裏沒有任何細微的內存泄漏。)

[...]所以變量很快就會被GC清除。

準確地說,當調用堆棧被彈出時,變量將被丟棄。這將最終導致Future對象無法訪問並且有資格進行垃圾回收。然而,該方法通常不會在方法返回時立即垃圾收集

+0

所以你建議在方法執行後,即使我沒有調用future.get(),對包裝結果的引用仍然會存在,因爲線程執行程序持有變量? – AntJavaDev

+0

是的,沒錯。 – aioobe

+0

@AntJavaDev未來正在執行的方法不會被中斷。它將完成,此時Executor將釋放其引用,Future對象將有資格進行垃圾回收。 – Sinkingpoint

0

您可以保證在定義對其引用的範圍內時該對象不會被GCed,或者代碼中的某處引用該對象。

這適用於所有對象,而Future在這裏沒有任何區別。

所以,一旦你的方法結束了,它的調用堆棧被清除了,在將來的某個時刻,你的對象將有資格進行垃圾收集,但是在引用它的方法的調用堆棧中肯定不會引用它。

1

我想。預定的未來將有一些線程隊列的內部引用,直到任務完成。所以在任務完成之前它不能被gc收集。

可能存在未來和執行者之間存在額外的抽象層次,未來可以收集。但是我確定如果提交的任務會被運行。無論如何,指向未來保存與否。