官术网_书友最值得收藏!

1.2 線程創(chuàng)建與運(yùn)行

Java中有三種線程創(chuàng)建方式,分別為實(shí)現(xiàn)Runnable接口的run方法,繼承Thread類并重寫run的方法,使用FutureTask方式。

首先看繼承Thread類方式的實(shí)現(xiàn)。

public class ThreadTest {
    //繼承Thread類并重寫run方法
    public static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("I am a child thread");
        }
    }
    public static void main(String[] args) {
        // 創(chuàng)建線程
        MyThread thread = new MyThread();
        // 啟動(dòng)線程
        thread.start();
    }
}

如上代碼中的MyThread類繼承了Thread類,并重寫了run()方法。在main函數(shù)里面創(chuàng)建了一個(gè)MyThread的實(shí)例,然后調(diào)用該實(shí)例的start方法啟動(dòng)了線程。需要注意的是,當(dāng)創(chuàng)建完thread對(duì)象后該線程并沒有被啟動(dòng)執(zhí)行,直到調(diào)用了start方法后才真正啟動(dòng)了線程。

其實(shí)調(diào)用start方法后線程并沒有馬上執(zhí)行而是處于就緒狀態(tài),這個(gè)就緒狀態(tài)是指該線程已經(jīng)獲取了除CPU資源外的其他資源,等待獲取CPU資源后才會(huì)真正處于運(yùn)行狀態(tài)。一旦run方法執(zhí)行完畢,該線程就處于終止?fàn)顟B(tài)。

使用繼承方式的好處是,在run()方法內(nèi)獲取當(dāng)前線程直接使用this就可以了,無須使用Thread.currentThread()方法;不好的地方是Java不支持多繼承,如果繼承了Thread類,那么就不能再繼承其他類。另外任務(wù)與代碼沒有分離,當(dāng)多個(gè)線程執(zhí)行一樣的任務(wù)時(shí)需要多份任務(wù)代碼,而Runable則沒有這個(gè)限制。下面看實(shí)現(xiàn)Runnable接口的run方法方式。

    public static class RunableTask implements Runnable{
        @Override
        public void run() {
            System.out.println("I am a child thread");
        }
    }
  public static void main(String[] args) throws InterruptedException{
        RunableTask task = new RunableTask();
        new Thread(task).start();
        new Thread(task).start();
  }

如上面代碼所示,兩個(gè)線程共用一個(gè)task代碼邏輯,如果需要,可以給RunableTask添加參數(shù)進(jìn)行任務(wù)區(qū)分。另外,RunableTask可以繼承其他類。但是上面介紹的兩種方式都有一個(gè)缺點(diǎn),就是任務(wù)沒有返回值。下面看最后一種,即使用FutureTask的方式。

//創(chuàng)建任務(wù)類,類似Runable
public static class CallerTask implements Callable<String>{
        @Override
        public String call() throws Exception {
            return "hello";
        }
    }
    public static void main(String[] args) throws InterruptedException {
    // 創(chuàng)建異步任務(wù)
        FutureTask<String> futureTask  = new FutureTask<>(new CallerTask());
        //啟動(dòng)線程
        new Thread(futureTask).start();
        try {
          //等待任務(wù)執(zhí)行完畢,并返回結(jié)果
            String result = futureTask.get();
            System.out.println(result);
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
}

如上代碼中的CallerTask類實(shí)現(xiàn)了Callable接口的call()方法。在main函數(shù)內(nèi)首先創(chuàng)建了一個(gè)FutrueTask對(duì)象(構(gòu)造函數(shù)為CallerTask的實(shí)例),然后使用創(chuàng)建的FutrueTask對(duì)象作為任務(wù)創(chuàng)建了一個(gè)線程并且啟動(dòng)它,最后通過futureTask.get()等待任務(wù)執(zhí)行完畢并返回結(jié)果。

小結(jié):使用繼承方式的好處是方便傳參,你可以在子類里面添加成員變量,通過set方法設(shè)置參數(shù)或者通過構(gòu)造函數(shù)進(jìn)行傳遞,而如果使用Runnable方式,則只能使用主線程里面被聲明為final的變量。不好的地方是Java不支持多繼承,如果繼承了Thread類,那么子類不能再繼承其他類,而Runable則沒有這個(gè)限制。前兩種方式都沒辦法拿到任務(wù)的返回結(jié)果,但是Futuretask方式可以。

主站蜘蛛池模板: 和硕县| 牡丹江市| 宣汉县| 延寿县| 定安县| 楚雄市| 凯里市| 灵川县| 天全县| 涟源市| 舟曲县| 兴海县| 六盘水市| 迭部县| 米林县| 惠水县| 伊川县| 嵊州市| 涿州市| 井冈山市| 松滋市| 上思县| 葫芦岛市| 罗城| 珠海市| 阿拉善右旗| 图们市| 商洛市| 剑阁县| 黔西| 普兰店市| 民乐县| 宁城县| 英德市| 孝昌县| 武胜县| 荃湾区| 鞍山市| 德惠市| 宁晋县| 永嘉县|