在傳統的同步開發模式下當我們調用一個函數時通過這個函數的參數將數據傳入並通過這個函數的返回值來返回最終的計算結果但在多線程的異步開發模式下數據的傳遞和返回和同步開發模式有很大的區別由於線程的運行和結束是不可預料的因此在傳遞和返回數據時就無法象函數一樣通過函數參數和return語句來返回數據本文就以上原因介紹了幾種用於向線程傳遞數據的方法在下一篇文章中將介紹從線程中返回數據的方法
欲先取之必先予之一般在使用線程時都需要有一些初始化數據然後線程利用這些數據進行加工處理並返回結果在這個過程中最先要做的就是向線程中傳遞數據
一通過構造方法傳遞數據
在創建線程時必須要建立一個Thread類的或其子類的實例因此我們不難想到在調用start方法之前通過線程類的構造方法將數據傳入線程並將傳入的數據使用類變量保存起來以便線程使用(其實就是在run方法中使用)下面的代碼演示了如何通過構造方法來傳遞數據
package mythread;
public class MyThread extends Thread
{
private String name;
public MyThread(String name)
{
thisname = name;
}
public void run()
{
Systemoutprintln(hello + name);
}
public static void main(String[] args)
{
Thread thread = new MyThread(world);
threadstart();
}
}
由於這種方法是在創建線程對象的同時傳遞數據的因此在線程運行之前這些數據就就已經到位了這樣就不會造成數據在線程運行後才傳入的現象如果要傳遞更復雜的數據可以使用集合類等數據結構使用構造方法來傳遞數據雖然比較安全但如果要傳遞的數據比較多時就會造成很多不便由於Java沒有默認參數要想實現類似默認參數的效果就得使用重載這樣不但使構造方法本身過於復雜又會使構造方法在數量上大增因此要想避免這種情況就得通過類方法或類變量來傳遞數據
二通過變量和方法傳遞數據
向對象中傳入數據一般有兩次機會第一次機會是在建立對象時通過構造方法將數據傳入另外一次機會就是在類中定義一系列的public的方法或變量(也可稱之為字段)然後在建立完對象後通過對象實例逐個賦值下面的代碼是對MyThread類的改版使用了一個setName方法來設置name變量
package mythread;
public class MyThread implements Runnable
{
private String name;
public void setName(String name)
{
thisname = name;
}
public void run()
{
Systemoutprintln(hello + name);
}
public static void main(String[] args)
{
MyThread myThread = new MyThread();
myThreadsetName(world);
Thread thread = new Thread(myThread);
threadstart();
}
}
三通過回調函數傳遞數據
上面討論的兩種向線程中傳遞數據的方法是最常用的但這兩種方法都是main方法中主動將數據傳入線程類的這對於線程來說是被動接收這些數據的然而在有些應用中需要在線程運行的過程中動態地獲取數據如在下面代碼的run方法中產生了個隨機數然後通過Work類的process方法求這三個隨機數的和並通過Data類的value將結果返回從這個例子可以看出在返回value之前必須要得到三個隨機數也就是說這個value是無法事先就傳入線程類的
package mythread;
class Data
{
public int value = ;
}
class Work
{
public void process(Data data Integer numbers)
{
for (int n : numbers)
{
datavalue += n;
}
}
}
public class MyThread extends Thread
{
private Work work;
public MyThread(Work work)
{
thiswork = work;
}
public void run()
{
javautilRandom random = new javautilRandom();
Data data = new Data();
int n = randomnextInt();
int n = randomnextInt();
int n = randomnextInt();
workprocess(data n n n); // 使用回調函數
Systemoutprintln(StringvalueOf(n) + + + StringvalueOf(n) + +
+ StringvalueOf(n) + = + datavalue);
}
public static void main(String[] args)
{
Thread thread = new MyThread(new Work());
threadstart();
}
}
在上面代碼中的process方法被稱為回調函數從本質上說回調函數就是事件函數在Windows API中常使用回調函數和調用API的程序之間進行數據交互因此調用回調函數的過程就是最原始的引發事件的過程在這個例子中調用了process方法來獲得數據也就相當於在run方法中引發了一個事件
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26623.html