天天看點

java建立新的線程 :有兩種方式 or 三種方式?

   在看很多的關于java建立新線程的部落格中,發現有的說建立新的線程有兩種方式,有的說是三種方式。但是到底是哪一種是正确的呢 ?

  • 兩種建立方式: 一種是将類聲明為Thread的子類,該類應重寫Thread類的run方法,另一種是實作Runnable接口,并實作run方法。
  • 三種建立方式: 在前面兩種的方式+ 第三種:實作Callable< V > 接口,實作call方法。

   首先是從這兩種結論可以看出:争論是在第三種實作Callable接口的方式 是不是java建立線程的方式!

我還是先看腳踏實地看下這三種建立新的線程的方式:

一. 将類聲明為Thread的子類,并重寫Thread類的run方法

private static class ThreadSon extends Thread{
        @Override
        public void run(){
            System.out.println("thread子方法:" + Thread.currentThread().getName());
        }
    }

    public static void main(String[] args) {
        System.out.println("main方法:" + Thread.currentThread().getName());
        ThreadSon threadSon = new ThreadSon();
        threadSon.start();
    }
           

執行結果:

java建立新的線程 :有兩種方式 or 三種方式?

二. 實作Runnable接口,重寫fun方法

private static class RunnableSon implements Runnable{
        @Override
        public void run() {
            System.out.println("runable子方法:" + Thread.currentThread().getName());
        }
    }
    
    public static void main(String[] args) {
        System.out.println("main方法:" + Thread.currentThread().getName());
        RunnableSon runnableSon = new RunnableSon();
        Thread t = new Thread(runnableSon);
        t.start();
    }
           

執行結果:

java建立新的線程 :有兩種方式 or 三種方式?

三. 實作Callable接口,實作call方法

private static class CallableSon  implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        System.out.println("子線程名稱:" + Thread.currentThread().getName());
        return 123456;
    }
}

public static void main(String[] args) {
    System.out.println("主線程:" + Thread.currentThread().getName());
    CallableSon callableSon = new CallableSon();
    FutureTask<Integer> futureTask = new FutureTask<>(callableSon);
    Thread thread = new Thread(futureTask);
    thread.start();
}
           

執行結果:

java建立新的線程 :有兩種方式 or 三種方式?

  從上面的運作結果上看,這三種方式都建立了新的線程,那麼 “三種建立方式”的結論是正确的。然而事實真的是這樣的嗎?????

四. 檢視JDK文檔

java建立新的線程 :有兩種方式 or 三種方式?

  由上圖可知,JDK官方文檔上明确說明,有兩種方式建立一個新的執行線程。

  由下圖可知,這兩種方式,一種是繼承Thread,重寫run方法;另一種實作Runnable接口,實作run方法。

  由此說明,java建立新的線程的方式是兩種!!!

java建立新的線程 :有兩種方式 or 三種方式?

五. 探究:為什麼實作Callable接口的方式不被JDK官方承認這是一種新的建立線程的方式呢??

private static class RunnableSon implements Runnable{
    @Override
    public void run() {
        System.out.println("runnable子方法:" + Thread.currentThread().getName());
    }
}

private static class CallableSon  implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        System.out.println("callable子方法:" + Thread.currentThread().getName());
        return 123456;
    }
}
public static void main(String[] args) {
    System.out.println("主線程:" + Thread.currentThread().getName());
    CallableSon callableSon = new CallableSon();
    FutureTask<Integer> futureTask = new FutureTask<>(callableSon);
    Thread thread = new Thread(futureTask);
    thread.start();

    RunnableSon runnableSon = new RunnableSon();
    Thread runThread = new Thread(runnableSon);
    runThread.start();
}
           

  由上面的代碼可知:Runnable和Callable都是通過new Thread(Runnable target)建立線程的,下面代碼是Thread的含參構造,并初始化一個線程。

public Thread(Runnable target) {
    init(null, target, "Thread-" + nextThreadNum(), 0);
}
           

  下面是Callable的官方說明,Callable類似與Runnable,并由他們共同使用同一個初始化線程的方法。又因為Runnable Jdk1.0 就已經出現,而Callable Jdk1.5才出現,是以JDK官方也隻是把他們倆算作一種建立線程的方式。

java建立新的線程 :有兩種方式 or 三種方式?

6. java 建立新的線程的方式是兩種:一種是将類聲明為Thread的子類,該類應重寫Thread類的run方法,另一種是實作Runnable接口,并實作run方法。

  以上第五部分是本人檢視源碼的了解:如有偏差或錯誤,請不吝賜教!!!