1. 程式人生 > 實用技巧 >如何建立執行緒

如何建立執行緒

執行緒建立

目錄

一. 執行緒建立的方式


Ⅰ. 繼承Thread類

  1. 自定義一個類,繼承Thread類
  2. 重寫run方法,run方法中用於定義當前執行緒的執行邏輯。
  3. 建立執行緒類的物件
  4. 開啟執行緒 Thread類中start()方法啟動執行緒
/**
 * 此案例展示第一種建立執行緒之方法:繼承Thread類
 * 說明:
 * 1.若 static 修飾 i,則共享i
 *
 * 關於Thread中的幾個方法:
 * 1.雖然main()也是一個執行緒,但若需要Thread中的函式,如yiled()或sleep()
 * 也需要繼承Thread,其本身不具有。
 * 2.線上程執行體中可以直接使用Thread中的方法如getName(),但main()中
 * 需要先返回當前執行緒物件。
 * 3.getName()是Thread類中的方法,若只是實現了Runnable介面,也需要先返回
 * 當前執行緒物件才能使用
 * 4.sleep() yiled()是Thread中的靜態方法
 */

public class FirstThread extends Thread {
    private int i;
    @Override
    public void run() {
        //繼承了getName()
        for (;i<100; i++) {
            System.out.println(getName() + " " + i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        for(int i = 0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+" "+i);
            if(i==20){
                new FirstThread().start();
                new FirstThread().start();
                //yield();
                sleep(1000);
            }
        }
    }
}

Ⅱ. 實現Runnable介面

  1. 自定義一個類 實現Runnable介面。
  2. 實現run方法。
  3. 建立一個自定義執行緒類的物件,但是該物件身上沒有start啟動執行緒的方法;可以建立Thread物件,將自定義執行緒類的物件作為引數傳入構造方法中。
  4. 呼叫start方法啟動執行緒
/**
 * 此案例展示建立執行緒的第二種方法:實現Runnable介面
 * 其實現類僅作為Thread類的target。(把run()包裝成一個Thread類)
 *
 * 說明:此方法中雖然new了兩個類物件,但都作為了一個Thread類的target
 * 所以共享了變數i
 *
 */
public class SecendThread implements Runnable {
    private int i;
    @Override
    public void run() {
        for(;i<100;i++){
            System.out.println(Thread.currentThread().getName()+" "+i);
        }
    }

    public static void main(String[] args) {
        for(int i = 0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+" "+i);
            if(i==20){
                SecendThread secendThread = new SecendThread();
                new Thread(secendThread,"執行緒一").start();
                new Thread(secendThread,"執行緒二").start();
            }
        }
    }
}

Ⅲ. 實現Runnable介面

  1. 自定義一個類 實現Callable介面
  2. 實現call方法 call方法中包含的是執行緒執行邏輯程式碼
  3. Executors獲取執行緒服務物件
  4. 呼叫執行緒服務物件submit,將自定義執行緒物件傳給submit方法的引數;submit返回值為Future型別,call方法的返回值就包含在Future物件中;可以通過future的get方法獲取返回值物件
public class ThreadDemo2 {
    public static void main(String[] args) throws Exception {
        //獲取執行緒池的服務 物件
        ExecutorService service = Executors.newCachedThreadPool();
        MyThread2 myThread2 = new MyThread2();
        //通過submit方法來執行執行緒
        Future future = service.submit(myThread2);
        //Future中包含了執行緒的返回值
        Object o = future.get();
        System.out.println(o);
    }
}

//自定義執行緒--方式三
class MyThread2 implements Callable{
    @Override
    public Object call() throws Exception {
        System.out.println("通過實現Callable介面自定義執行緒~~");
        return "hello";
    }
}

三. 對比總結


  1. 只有方法一需要繼承Thread類,不如後兩者。

  2. 只有方法三可以有返回值,可以丟擲異常。

  3. Callable通過泛型來定義返回結果型別。在實際開發過程中和Runnable相似,如果需要執行結果那麼使用Callable。

    Runnable Callable
    返回值 沒有 通過泛型來定義返回值型別
    啟動方式 1.通過Thread直接啟動
    2.通過執行緒池的execute或者submit方法啟動
    1.通過FutureTask轉化成Runnable之後再通過Thread啟動
    2.通過執行緒池的submit方法啟動
    ⭐️異常處理 1.不允許拋異常,那麼就無法通過全域性方法來處理。
    允許拋異常,能通過全域性方式來統一處理。