2010-06-29 73 views
41

比方說,我們有這個簡單的例子:線程在完成工作後如何返回值?

public Example extends Thread{ 

    String temp;  

    public Example(){ 
    } 

    @Override 
    public void run(){ 
     . 
     . 
     . 
     . 
     temp = "a_value"; 
    } 

    public static void main(String[] args) { 

     Example th = new Example(); 
     th.start(); 
    } 

} 

如何能完成其工作後的線程返回我的字符串溫度?

+1

它應該是'th.start()'。你確實實現了從線程返回值的方法之一。 – 2010-06-29 13:41:53

回答

7

您可以通過觀察者模式實現此目的。 完成線程通知所有偵聽器它已完成,並且它們可以檢索該值(通過獲取器)。或者它甚至可以發送計算值。

或者您可以使用一個任務,請參閱FutureTask,這是一個可運行(實際上如Callable所述),它返回結果並可以拋出異常。

11

看看Future接口javadoc。它有示例用法,向您顯示如何執行此操作。

63

利用(相對)新Callable<T>而不是Runnable接口的(在1.5和更新版本):

這裏是一個(簡單的)例子:

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


public class Main { 

    public static void main(final String[] argv) { 
     final ExecutorService service; 
     final Future<String> task; 

     service = Executors.newFixedThreadPool(1);   
     task = service.submit(new Foo()); 

     try { 
      final String str; 

      // waits the 10 seconds for the Callable.call to finish. 
      str = task.get(); // this raises ExecutionException if thread dies 
      System.out.println(str); 
     } catch(final InterruptedException ex) { 
      ex.printStackTrace(); 
     } catch(final ExecutionException ex) { 
      ex.printStackTrace(); 
     } 

     service.shutdownNow(); 
    } 
} 

class Foo implements Callable<String> { 
    public String call() { 
     try { 
      // sleep for 10 seconds 
      Thread.sleep(10 * 1000); 
     } catch(final InterruptedException ex) { 
      ex.printStackTrace(); 
     } 

     return ("Hello, World!"); 
    } 
} 
+2

「(相對)新」相對於什麼?它是在現已完成使用壽命期的版本中推出的。 – 2010-06-29 14:18:11

+20

相對於發佈... 1.6是最新版本,它在1.5版本發佈。將其與1.0中的Thread進行比較......學生們從中學習的很多書中沒有Callable。 – TofuBeer 2010-06-29 14:27:30

+7

一如既往的例子我只想知道wtf是foo – jiduvah 2012-06-06 15:31:42

0

如果你不想交換解決方案以使用Callable對象,那麼您也可以使用隊列並以這種方式從線程返回結果。
我重新寫你的例子是這樣的:

import java.util.PriorityQueue; 
import java.util.Queue; 

public class GetResultFromThread { 
    public static void main(String[] args) throws Exception { 
     Queue<String> queue = new PriorityQueue<String>(); 
     int expectedResults = 2; 
     for (int i = 0; i < expectedResults; i++) { 
      new Example(queue).start(); 
     } 

     int receivedResults = 0; 
     while (receivedResults < expectedResults) { 
      if (!queue.isEmpty()) { 
       System.out.println(queue.poll()); 
       receivedResults++; 
      } 
      Thread.sleep(1000); 
     } 
    } 
} 

class Example extends Thread { 
    private final Queue<String> results; 

    public Example(Queue<String> results) { 
     this.results = results; 
    } 

    @Override 
    public void run() { 
     results.add("result from thread"); 
    } 
} 

請注意,您應考慮同步和併發的!

+3

而不是僅僅點擊向下箭頭,並說這是一個不好的解決方案,如果你解釋爲什麼會很好。謝謝 – thomasb 2015-11-27 07:18:50

+0

其實我這個@ Martin的解決方案非常聰明,謝謝你的 – Benvorth 2016-08-27 13:04:07

相關問題