java多執行緒學習(1) java執行緒Runnable,Thread,Callable,FutureTask

2020-10-29 11:01:26

執行緒建立的方式

1.Thread物件

1.1 繼承Thread物件

@Slf4j
public class MyThread extends Thread{
    @Override
    public void run() {
        // 執行緒要執行的內容
        log.debug("繼承Thread方式");
    }
}

public class Test1 {
    public static void main(String[] args) {
        new MyThread().start(); // 啟動執行緒
    }
}

1.2 直接使用Thread物件

public class Test1 {
    public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run() {
                log.debug("執行緒執行");
            }
        };
        t.start();
    }
}

2.Runnable介面

public class MyThread implements Runnable{
    @Override
    public void run() {
        // 該執行緒執行內容
        System.out.println("執行緒執行");
    }
}

public static void main(String[] args) {
        MyThread myThread = new MyThread();
        Thread t1 = new Thread(myThread, "t1");
        t1.start();

        // jdk8 Lambda
        Thread t2 = new Thread(()->{ System.out.println("t2執行");}, "t1");
        t2.start();

        Runnable runnable = ()->{ System.out.println("t3執行"); };
        Thread t3 = new Thread(runnable, "t3");
        t3.start();
    }

3.Runnable和Thread的關係

Runnable的執行需要傳入Thread中執行

      Runnable runnable = ()->{ System.out.println("t3執行"); };
      Thread t3 = new Thread(runnable, "t3");
      t3.start();

點開Thread原始碼發現會把Runnable傳個init方法

https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202010/20201027204059703jvgja4qd0by.png
發現init又傳給另外一個init
在這裡插入圖片描述
該init方法中發現他又傳給了自身的一個變數

在這裡插入圖片描述
發現在Thread類中的run()方法最終呼叫了這個Runnable的run方法

在這裡插入圖片描述

Runnable的run最終還是走的Thread的run,如果不重新run方法的情況下Thread的run方法會優先判斷是否有Runnable傳入,如果有那麼就執行Runnable的run方法

3.Callable和FutureTask

FutureTask本身實現RunnableFuture

public class FutureTask<V> implements RunnableFuture<V>

RunnableFuture 又多繼承了Runnable和Future

public interface RunnableFuture<V> extends Runnable, Future<V>

也就是說FutureTask也可以看做一個Runnable但是又強於Runnable
因為還繼承了Future中的方法賦予了它獲取執行緒執行結果的能力
在這裡插入圖片描述
Callable只是一個介面其call 和 Runnable的run方法性質差不多,都是執行緒要執行其中的程式碼,但call有返回值的泛型同時也能做異常的丟擲,run方法就不具備異常也得內部自己消化

在這裡插入圖片描述

但我們執行程式碼的時候還是用的 start方法其還是去跑run方法,但發現我們這裡並沒有重寫run方法而是一個call方法

在這裡插入圖片描述

點開FutureTask 類,發現其內部重寫了run方法,當我們在start啟動執行緒的時候該run方法會去呼叫其傳入的Callable的call方法,並在這裡做了異常的處理並在這個時候把值返回給FutureTask的set方法供get等方法的呼叫

在這裡插入圖片描述

值返回給變數outcome

在這裡插入圖片描述
呼叫get方法的時候呼叫其report方法
在這裡插入圖片描述
該方法的返回就是run方法呼叫call的值

在這裡插入圖片描述
注意
在這裡插入圖片描述
看到get方法有返回值,也就是說他會一直阻塞到執行緒非同步的返回