1. 程式人生 > 其它 >【9034期】JUC多執行緒---建立執行緒的四種方式

【9034期】JUC多執行緒---建立執行緒的四種方式

在 Java 中,實現多執行緒的主要有以下四種:

(1)繼承 Thread 類,重寫 run() 方法;
(2)實現 Runnable 介面,實現 run() 方法,並將 Runnable 實現類的例項作為 Thread 建構函式的引數 target;
(3)實現 Callable 介面,實現 call() 方法,然後通過 FutureTask 包裝器來建立 Thread 執行緒;
(4)通過 ThreadPoolExecutor 建立執行緒池,並從執行緒池中獲取執行緒用於執行任務;

第(1)(2)種方式無法獲取執行緒的執行結果,因為通過重寫的 run() 方法的返回值是void;第(3)種方式可以獲取執行緒的執行結果,因為通過 Callable 介面的 call() 方法的返回值是 Object,可以將返回的結果可以放在 Object 物件中;第(4)種方式對於兩種情況都支援,具體取決於任務的型別,有返回值的任務必須實現 Callable 介面,無返回值的任務必須實現 Runnable 介面。

繼承Thread類的方式

Thread 實現了 Runnable 介面,代表一個執行緒的例項。啟動執行緒的唯一方法就是通過 Thread 類的start() 方法。start() 方法是一個native方法,它將啟動一個新執行緒,並執行run()方法。

這種方式實現多執行緒很簡單,直接 extends Thread,並重寫 run() 方法,就可以啟動新執行緒執行自己定義的run()方法。

通過實現 Runnable 介面

通過實現 Runnable 介面,實現 run() 方法,將 Runnable 介面的實現類的例項作為 Thread 的帶參建構函式中,並通過呼叫 start() 方法啟動執行緒。

實現 Runnable 介面比繼承 Thread 類所具有的優勢主要有:

① 可以避免 JAVA 中單繼承的限制;
② 執行緒池只能放入實現 Runable 或 Callable類執行緒,不能直接放入繼承 Thread 的類
③ 程式碼可以被多個執行緒共享,程式碼和資料獨立,適合多個相同的程式程式碼的執行緒去處理同一個資源的情況

實現Callable介面,並通過FutureTask包裝器來建立Thread執行緒

(1)實現 Callable 介面,並實現 call() 方法;
(2)建立 Callable 介面的實現類的例項,使用 FutureTask 類包裝 Callable 物件,該 FutureTask 物件封裝了 Callable 物件的 call() 方法的返回值;
(3)使用 FutureTask 物件作為 Thread 類的建構函式的 target 引數建立並啟動執行緒;
(4)呼叫 FutureTask 物件的 get() 來獲取子執行緒執行結束的返回值;

public class ThreadDemo03 {
    public static void main(String[] args) {
        Callable<Object> oneCallable = new Tickets<Object>();
        FutureTask<Object> oneTask = new FutureTask<Object>(oneCallable);
        Thread t = new Thread(oneTask);
        System.out.println(Thread.currentThread().getName());
        t.start();
    }
}
class Tickets<Object> implements Callable<Object>{
    //重寫call方法
    @Override
    public Object call() throws Exception {
        System.out.println(Thread.currentThread().getName()+"-->我是通過實現Callable介面通過FutureTask包裝器來實現的執行緒");
        return null;
    }   
}

使用ThreadPoolExecutor 建立執行緒池

使用 ThreadPoolExecutor 建立執行緒池,並從執行緒池中獲取執行緒用於執行任務。

ExecutorService、Callable、Future 實際上都是屬於 Executor 框架。執行緒池支援有返回結果和無返回結果的任務,有返回值的任務必須實現Callable介面,無返回值的任務必須實現Runnable介面。對於有結果的任務,執行 Callable 任務後,可以獲取一個 Future 的物件,在該物件上呼叫 get 就可以獲取到Callable任務返回的 Object 了,但需要注意的是:get方法是阻塞的,如果執行緒未返回結果,那麼 get() 方法會一直等待,直到有結果返回或者超時。

吃水不忘挖井人: