2012-08-10 57 views
6

我想了解Callable在不同的線程上運行時能夠返回一個值。Callable如何在引擎蓋下工作?可調用對象如何返回值?

我在找類Executors,AbstractExecutorService,ThreadPoolExecutorFutureTask,全部可在java.util.concurrent包中找到。

您可以通過調用Executors中的方法(例如newSingleThreadExecutor())來創建ExecutorService對象。然後你可以傳遞一個Callable對象ExecutorService.submit(Callable c)

由於call()方法由ExecutorService提供的線程運行,返回的對象在哪裏跳轉回調用線程?

看這個簡單的例子:

1 ExecutorService executor = Executors.newSingleThreadExecutor(); 
2 public static void main(String[] args) { 
3  Integer i = executor.submit(new Callable<Integer>(){ 
4   public Integer call() throws Exception { 
5    return 10; 
6   } 
7  }).get(); 
8  System.out.print("Returns: " + i + " Thread: " + Thread.currentThread.getName()); 
9  // prints "10 main" 
10 } 

怎麼可能的是,在呼叫的方法,這是由一個單獨的線程上運行,該整數被返回到整數對象(第3行),因此它可以由主線程(第7行)中的System.out語句打印?

ExecutorService運行其線程之前,主線程不可能運行,因此System.out statement將打印爲空?

+0

這段代碼有一些編譯錯誤;例如'executor.submit'返回Future,而不是Integer,'currentThread'是需要調用的方法。如果有人關心看到一個工作示例,請參閱http://ideone.com/myoMB – 2012-08-10 14:25:16

+0

對不起,我手動編寫該代碼。 :-)我會看看你的例子。 – Rox 2012-08-10 14:40:11

+0

哦,沒問題,我只是想幫助。這是一個很好的問題。 +1 – 2012-08-10 15:15:42

回答

8

怎麼可能在調用方法,它是由一個單獨的線程運行,整數返回到Integer對象

ExecutorService.submit(...)返回從call()的對象,但它確實會返回Future<Integer>,您可以使用Future.get()方法獲取該對象。請參閱下面的示例代碼。

在ExecutorService運行其線程之前運行主線程是不可能的,以便System.out語句打印出null?

不,未來的方法get()等待,直到工作完成。如果call()返回null,則get()將以其他方式返回(並打印)10保證。

Future<Integer> future = executor.submit(new Callable<Integer>(){ 
    public Integer call() throws Exception { 
     return 10; 
    } 
}); 
try { 
    // get() waits for the job to finish before returning the value 
    // it also might throw an exception if your call() threw 
    Integer i = future.get(); 
    ... 
} catch (ExecutionException e) { 
    // this cause exception is the one thrown by the call() method 
    Exception cause = e.getCause(); 
    ... 
} 
+0

謝謝你的回答!等待發生在哪裏?它必須進行一些同步,以便調用線程(例如主線程)可以等待ExecutorService完成其任務。我查看了FutureTask和ThreadPoolExecutor,並且看不到這樣的同步。 – Rox 2012-08-11 09:32:45

+0

它是否像這樣工作,即主ExecutorService進入'RunnableFuture.run()'方法之前主線程進入'Future.get()'方法,但主方法必須等待ExecutorService完成運行)方法,當它有,它notifys主線程進行get()方法? – Rox 2012-08-11 10:36:50

+2

'Future.get()'做了等待。在'FutureTask'裏面,我認爲'acquireSharedInterruptibly(0)',然後調用'doAcquireSharedInterruptibly(...)'進行同步和等待。同步通過'volatile'完成。 – Gray 2012-08-11 12:55:25

4

ExecutorService.submit()方法請看:

<T> Future<T> submit(Callable<T> task): 提交一個返回值的任務用於執行,返回表示任務的未決結果的Future。未來的get方法將在成功完成時返回任務的結果。 如果您想立即阻塞任務的等待,你可以使用表格的結構result = exec.submit(aCallable).get();


Q. Isn't有可能爲ExecutorService的面前將要運行的主線程運行它的線程,以便System.out語句打印出null?

- >Future<T>.get()如果需要,等待計算完成,然後檢索其結果。

+0

感謝您的回答。看看我的問題,格雷的答案。同步發生在何處,以便主線程可以等待ExecutorService完成其任務? – Rox 2012-08-11 09:34:33

相關問題