2010-04-06 58 views
4

我有以下的Java代碼:java.util.concurrent.Future.get()沒有返回

final Future future = exeService.submit(
    new Runnable() { 
     public void run() { 
      myObject.doSomething(); 
     } 
    } 
); 

future.get(); 

其中exeService

java.util.concurrent.ExecutorService 

實例的問題是,myObject.doSomething()永遠不會返回,因此,future.get()永遠不會返回。

但是,如果我有像這樣execute調用替換調用submit

exeService.execute(
    new Runnable() { 
     public void run() { 
      myObject.doSomething(); 
     } 
    } 
); 

調用myObject.doSomething()不會返回。我不知道它是否重要,但doSomething()void方法。

爲什麼doSomething()在使用execute時完成,但在使用submit時沒有完成?

而且,我並不需要使用Future.get();這似乎是這樣做的最自然的方式。 (我也碰到與CountdownLatch同樣的問題。)問題的關鍵是,我需要等待doSomething()繼續之前完成,而且,對於複雜的原因,我不會進入這裏,我需要啓動它在一個單獨的線程。如果有另一種方法可行,那就沒問題了。

+2

你在問'doSomething'的行爲,但不會告訴我們任何事情。我們不能幫你在這裏... – 2010-04-06 15:15:53

+0

你的問題很混亂。第一個構造應該正常工作。困惑在於「迴歸」。難道你不是指「完成」或「執行」?你的困惑似乎基於這樣一個事實,即future.get()實際上等待可執行完成,因此會阻塞該線程並阻止它執行'future.get()之後的代碼剩餘部分)'線。 – BalusC 2010-04-06 15:17:54

+0

你是如何創建'exeService'的?它是一個ThreadPoolExecutor或其他東西? – nos 2010-04-06 15:39:37

回答

15

正如Executor.execute() Javadoc

在一些 在未來的時間執行給定的命令。該命令可以執行 在一個新的線程,在池 線程,或者調用線程,在 執行人 執行的自由裁量權。

因此,方法​​立即返回,讓您無法查詢提交任務的狀態。

在另一方面ExecutorService.submit()

提交一個Runnable任務用於執行 並返回表示 任務的Future。未來的get方法將在成功完成 時返回空值 。

Future.get()會在你的情況下成功賽區後返回只有,所以從未

這進一步Future.get() documentation指出:

如有必要,等待計算 完成,然後獲取其 結果。

+0

* never *?所以你暗示'myObject.doSomething();'就像是一個無限循環?爲什麼其他的構造能夠工作呢?請記住,'void'是一個完全有效的返回值。 – BalusC 2010-04-06 15:24:50

+0

我不*暗示*相當*結論* :-)。作者說「問題是,myObject.doSomething()永遠不會返回」,所以我認爲這個函數是類似無限循環(如服務器線程或某事)。 – pajton 2010-04-06 15:26:58

+2

是的。那麼你如何解釋當使用'execute()'而不是'submit()'時它會「返回」? – BalusC 2010-04-06 15:37:50

7

我創建了一個SSCCE

package com.stackoverflow.q2585971; 

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 

public class Test { 

    public static void main(String args[]) throws Exception { 
     ExecutorService executor = Executors.newCachedThreadPool(); 
     Future<?> future = executor.submit(
      new Runnable() { 
       public void run() { 
        try { 
         Thread.sleep(1000); 
        } catch (InterruptedException e) { 
         System.out.println("Epic fail."); 
        } 
       } 
      } 
     ); 

     System.out.println("Waiting for task to finish.."); 
     future.get(); 
     System.out.println("Task finished!"); 
     executor.shutdown(); 
    } 

} 

它完美的罰款。它首先打印

Waiting for task to finish..

一秒鐘後,您會看到

Task finished!

所以,你的問題就出在別處。我會在這裏複製我對你的問題的評論:

你的問題很混亂。第一個構造應該正常工作。困惑在於「迴歸」。難道你不是指「完成」或「執行」?您的困惑似乎基於這樣一個事實,即future.get()實際上等待可運行完成,因此將阻止該線程並阻止其執行future.get()行後的代碼剩餘部分。

0

檢查doSomething中的死鎖。

我將開始搜索wait調用。

如果您的wait對於某些事情,您需要通過調用notifynotifyAll來通知您從另一個線程等待的對象。

1

Java期貨封鎖! get(). This method blocks the current thread until a future instance completes its work, thus requiring the use of one thread more than the work that must be performed just to manage what happens when it is done