1. 程式人生 > >從執行緒返回資料的兩種方法

從執行緒返回資料的兩種方法

執行緒中返回資料和向執行緒傳遞資料類似。也可以通過類成員以及回撥函式來返回資料。但類成員在返回資料和傳遞資料時有一些區別,下面讓我們來看看它們區別在哪。

一、通過類變數和方法返回資料

使用這種方法返回資料需要在呼叫start方法後才能通過類變數或方法得到資料。讓我們先來看看例程2-13會得到什麼結果。

  1. package mythread;  
  2. publicclass MyThread extends Thread  
  3. {  
  4. private String value1;  
  5. private String value2;  
  6. publicvoid run()  
  7.     {  
  8.         value1 = 
    "通過成員變數返回資料";  
  9.         value2 = "通過成員方法返回資料";  
  10.     }  
  11. publicstaticvoid main(String[] args) throws Exception  
  12.     {  
  13.         MyThread thread = new MyThread();  
  14.         thread.start();  
  15.         System.out.println("value1:" + thread.value1);  
  16.         System.out.println("value2:" + thread.value2);  
  17.     }  
  18. }  

執行上面的程式碼有可能輸出如下的結果:

value1:null
value2:null

從上面的執行結果看很不正常。在run方法中已經對value1和value2賦了值,而返回的卻是null。發生這種情況的原因是呼叫start方法後就立刻輸出了value1和value2的值,而這裡run方法還沒有執行到為value1和value2賦值的語句。要避免這種情況的發生,就需要等run方法執行完後才執行輸出value1和value2的程式碼。因此,我們可以想到使用sleep方法將主執行緒進行延遲,如可以在thread.start()後加一行如下的語句:

sleep(1000);

這樣做可以使主執行緒延遲1秒後再往下執行,但這樣做有一個問題,就是我們怎麼知道要延遲多長時間。在這個例子的run方法中只有兩條賦值語句,而且只建立了一個執行緒,因此,延遲1秒已經足夠,但如果run方法中的語句很複雜,這個時間就很難預測,因此,這種方法並不穩定。

我們的目的就是得到value1和value2的值,因此,只要判斷value1和value2是否為null。如果它們都不為null時,就可以輸出這兩個值了。我們可以使用如下的程式碼來達到這個目的:

  1. while (thread.value1 == null || thread.value2 == null); 

使用上面的語句可以很穩定地避免這種情況發生,但這種方法太耗費系統資源。大家可以設想,如果run方法中的程式碼很複雜,value1和value2需要很長時間才能被賦值,這樣while迴圈就必須一直執行下去,直到value1和value2都不為空為止。因此,我們可以對上面的語句做如下的改進:

  1. while (thread.value1 == null || thread.value2 == null)  
  2.     sleep(100); 

在while迴圈中第判斷一次value1和value2的值後休眠100毫秒,然後再判斷這兩個值。這樣所佔用的系統資源會小一些。

上面的方法雖然可以很好地解決,但Java的執行緒模型為我們提供了更好的解決方案,這就是join方法。在前面已經討論過,join的功能就是使用執行緒從非同步執行變成同步執行。當執行緒變成同步執行後,就和從普通的方法中得到返回資料沒有什麼區別了。因此,可以使用如下的程式碼更有效地解決這個問題:

thread.start();
thread.join();

在thread.join()執行完後,執行緒thread的run方法已經退出了,也就是說執行緒thread已經結束了。因此,在thread.join()後面可以放心大膽地使用MyThread類的任何資源來得到返回資料。

二、通過回撥函式返回資料

其實這種方法已經在《向執行緒傳遞資料的三種方法》中介紹了。在《向執行緒傳遞資料的三種方法》一文的例子中通過Work類的process方法向執行緒中傳遞了計算結果,但同時,也通過process方法從執行緒中得到了三個隨機數。因此,這種方法既可以向執行緒中傳遞資料,也可以從執行緒中獲得資料。