在看很多的關于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();
}
執行結果:

二. 實作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();
}
執行結果:
三. 實作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();
}
執行結果:
從上面的運作結果上看,這三種方式都建立了新的線程,那麼 “三種建立方式”的結論是正确的。然而事實真的是這樣的嗎?????
四. 檢視JDK文檔
由上圖可知,JDK官方文檔上明确說明,有兩種方式建立一個新的執行線程。
由下圖可知,這兩種方式,一種是繼承Thread,重寫run方法;另一種實作Runnable接口,實作run方法。
由此說明,java建立新的線程的方式是兩種!!!
五. 探究:為什麼實作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官方也隻是把他們倆算作一種建立線程的方式。
6. java 建立新的線程的方式是兩種:一種是将類聲明為Thread的子類,該類應重寫Thread類的run方法,另一種是實作Runnable接口,并實作run方法。
以上第五部分是本人檢視源碼的了解:如有偏差或錯誤,請不吝賜教!!!