天天看點

Java多線程初學者指南(7):向線程傳遞資料的三種方法

本文為原創,如需轉載,請注明作者和出處,謝謝!

在傳統的同步開發 模式下,當我們調用一個函數時,通過這個函數的參數将資料傳入,并通過這個函數的傳回值來傳回最終的計算結果。但在多線程的異步開發模式下,資料的傳遞和 傳回和同步開發模式有很大的差別。由于線程的運作和結束是不可預料的,是以,在傳遞和傳回資料時就無法象函數一樣通過函數參數和return語句來傳回資料。本文就以上原因介紹了幾種用于向線程傳遞資料的方法,在下一篇文章中将介紹從線程中傳回資料的方法。

    欲先取之,必先予之。一般在使用線程時都需要有一些初始化資料,然後線程利用這些資料進行加工處理,并傳回結果。在這個過程中最先要做的就是向線程中傳遞資料。

一、通過構造方法傳遞資料

在建立線程時,必須要建立一個Thread類的或其子類的執行個體。是以,我們不難想到在調用start方法之前通過線程類的構造方法将資料傳入線程。并将傳入的資料使用類變量儲存起來,以便線程使用(其實就是在run方法中使用)。下面的代碼示範了如何通過構造方法來傳遞資料:

package mythread;

public class MyThread1 extends Thread

{

    private String name;

    public MyThread1(String name)

    {

        this.name = name;

    }

    public void run()

        System.out.println("hello " + name);

    public static void main(String[] args)

        Thread thread = new MyThread1("world");

        thread.start();       

}

    由于這種方法是在建立線程對象的同時傳遞資料的,是以,線上程運作之前這些資料就就已經到位了,這樣就不會造成資料線上程運作後才傳入的現象。如果要傳遞 更複雜的資料,可以使用集合、類等資料結構。使用構造方法來傳遞資料雖然比較安全,但如果要傳遞的資料比較多時,就會造成很多不便。由于Java沒有預設參數,要想實作類似預設參數的效果,就得使用重載,這樣不但使構造方法本身過于複雜,又會使構造方法在數量上大增。是以,要想避免這種情況,就得通過類方法或類變量來傳遞資料。

二、通過變量和方法傳遞資料

    向對象中傳入資料一般有兩次機會,第一次機會是在建立對象時通過構造方法将資料傳入,另外一次機會就是在類中定義一系列的public的方法或變量(也可稱之為字段)。然後在建立完對象後,通過對象執行個體逐個指派。下面的代碼是對MyThread1類的改版,使用了一個setName方法來設定name變量:

package mythread;

public class MyThread2 implements Runnable

    public void setName(String name)

        MyThread2 myThread = new MyThread2();

        myThread.setName("world");

        Thread thread = new Thread(myThread);

        thread.start();

三、通過回調函數傳遞資料

    上面讨論的兩種向線程中傳遞資料的方法是最常用的。但這兩種方法都是main方法中主動将資料傳入線程類的。這對于線程來說,是被動接收這些資料的。然而,在有些應用中需要線上程運作的過程中動态地擷取資料,如在下面代碼的run方法中産生了3個随機數,然後通過Work類的process方法求這三個随機數的和,并通過Data類的value将結果傳回。從這個例子可以看出,在傳回value之前,必須要得到三個随機數。也就是說,這個value是無法事先就傳入線程類的。

class Data

    public int value = 0;

class Work

    public void process(Data data, Integer

Java多線程初學者指南(7):向線程傳遞資料的三種方法

 numbers)

        for (int n : numbers)

        {

            data.value += n;

        }

public class MyThread3 extends Thread

    private Work work;

    public MyThread3(Work work)

        this.work = work;

        java.util.Random random = new java.util.Random();

        Data data = new Data();

        int n1 = random.nextInt(1000);

        int n2 = random.nextInt(2000);

        int n3 = random.nextInt(3000);

        work.process(data, n1, n2, n3);   // 使用回調函數

        System.out.println(String.valueOf(n1) + "+" + String.valueOf(n2) + "+"

                + String.valueOf(n3) + "=" + data.value);

        Thread thread = new MyThread3(new Work());

在上面代碼中的process方法被稱為回調函數。從本質上說,回調函數就是事件函數。在Windows API中常使用回調函數和調用API的程式之間進行資料互動。是以,調用回調函數的過程就是最原始的引發事件的過程。在這個例子中調用了process方法來獲得資料也就相當于在run方法中引發了一個事件。