1. 程式人生 > >JAVA多執行緒入門(二):JAVA中如何寫多執行緒

JAVA多執行緒入門(二):JAVA中如何寫多執行緒

第一種方式:繼承Thread

步驟:

1.建立執行緒類,繼承自Thread + 重寫run,run中寫執行緒體,執行緒體就是mian()函式裡面的寫法

2.使用執行緒:

2.1 建立執行緒物件

2.2 執行緒物件.start()

步驟展示:

1.

public class Rabbit extends Thread {//執行緒類,繼承自Thread
    @Override
    public void run() {//在IDEA中可以通過ctrl+o快捷鍵快速重寫父類函式
        super.run();
        for(int i=0;i<1000;i++){
            System.out.println("兔子跑了"+i+"步");
        }
    }
}

2.

public class RabbitAPP {
    public static void main(String[] args){
        Rabbit rabbit = new Rabbit();//2.1 建立物件
        rabbit.start();//只是加到執行緒組裡面,等待CPU呼叫。CPU是自動呼叫的,所以不需要你自己寫程式。
    //注意,不要呼叫run方法。如果你呼叫run方法,相當於是呼叫函式而已,沒有用到執行緒方面的內容。
    }
}

第二種方式:通過Runnable介面

為什麼有了第一種方式還要使用第二種方式呢?因為Java只支援單繼承,如果一個類必須繼承自A類,那就無法繼承Thread類,所以必須實現介面來實現多執行緒。

步驟:

1.類實現Runnable介面+重寫run()  ------->真實角色類

2.使用執行緒

2.1 建立真實角色

2.2 建立代理(Thread類)

2.3 代理.start()

這裡用到了代理設計模式,你可以先了解一下,基本來說代理設計模式就是:

1.真實類與代理類實現共同介面。

2.代理類中含有真實類引用,並且呼叫真實類方法。

總結來說就是代理類間接行使真實類的方法。

為什麼要這麼做呢?你看,哪怕是通過介面,最後還不是要通過Thread類來呼叫.start()?換句話說,當我們不想或者無法從Thread中繼承出類,但是我們還得用Thread類的時候,那我們應該怎麼辦?

我們應該,想辦法將我們寫的類和Thread之間構建一個關係。怎麼構建關係?把我們寫的類當做一個引數傳遞進去不就好了麼。但是問題又來了,我們是把類傳遞進去了,但是類的寫法多樣,實現功能也大相徑庭,憑什麼去保證你的類作為引數傳遞進Thread的時候,能恰好合適呢?哦,我們可以讓他們按照某種規範,或者某種準則。等等,規範?準則?那我懂了,介面!只要讓Thread和我們寫的類都派生於同一個介面不就好了麼?然後在這個接口裡寫上至少一個必須重寫的函式。這樣,當我們寫的類傳遞進Thread類的時候,Thread會在內部呼叫我們的run()函式,而我們無需關係Thrad在內部做了些什麼,豈不美哉?

好了,下面給出例項程式碼:

1.

package com.njust.MyThread;

public class Programmer implements Runnable {
    @Override
    public void run() {
        for(int i=0;i<1000;i++)
            System.out.println("一邊敲程式碼");
}
}

2.

package com.njust.MyThread;

public class ProgrammerApp {
    public static void main(String[] args){
        Programmer programmer = new Programmer();
        Thread proxy = new Thread(programmer);
        proxy.start();
        for(int i=0;i<1000;i++)
            System.out.println("一邊聊QQ");
    }
}

 第三種方式:通過Callable介面

好處是可以返回值,也能丟擲異常。Callable時Runnable的加強版。

1.建立Callable實現類+重寫call

2.藉助 執行排程服務 ExecutorService,獲取Future物件

ExecutorService ser = Executors.newFixedThreadPool(n);//n代表開啟多少個執行緒

Future result = ser.submit(實現類物件)

3.獲取值reslut.get();

4.停止服務ser.shutdownNow();

package com.njust.MyThread;

import java.util.concurrent.*;

public class Call {
    public static void main(String[] args){
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        Race racer = new Race();
        Future<Integer> res = executorService.submit(racer);
        int num = 0;
        try {
            num = res.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        executorService.shutdownNow();
        System.out.println(num);

    }
}

class Race implements Callable<Integer> {//這裡的泛型是返回值型別

    @Override
    public Integer call() throws Exception {
        return 1000;
    }
}