Java單線程有三種實現方法
- 繼承
Thread
類,重寫run()
,無返回值 - 實現
Runnable
接口,重寫run()
,無返回值 - 實現
Callable<V>
接口,重寫call()
方法,有返回值
Java的單線程框架
這三種實現方式都是套用的一個線程框架,以下是簡化的Thread
類源碼:
// 線程任務定義接口
public interface Runnable {
public abstract void run();
}
// 線程類實現(源碼簡化版)
public class Thread implements Runnable {
private Runnable target;// 線程任務
public Thread() {
}
public Thread(Runnable target) {
this.target = target;
}
@Override
public void run() {
if (target != null) {
target.run();
}
}
public synchronized void start() {
start0();
}
// native方法由JVM底層C++實現,負責線程資源分配並啓動
// 線程運行起來以後,會調用Java線程對象的run()方法執行線程任務
private native void start0();
}
第一種方法:繼承Thread類
這種方法的實現原理是利用面向對象編程的三大特性之一:
繼承
通過繼承父類Thread
重寫run()
方法,達到線程任務的具體化。
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("重寫框架的線程任務調用邏輯");
}
public static void main(String[] args) {
new MyThread().start();
}
}
第二種方法:實現Runnable接口
這種方法纔是單線程Thread
的框架本意,通過Thread
構造方法接收線程任務,然後運行自身定義好的run()
方法邏輯,執行線程任務。
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("實現具體的線程任務");
}
public static void main(String[] args) {
new Thread(() -> System.out.println("線程任務")).start();
}
}
第三種方法:實現Callable接口
這種方法與前兩種方法最大的區別就是有返回值,啓動線程並執行任務的代碼途徑與第二種方法一樣,只是多了一層FutureTask
封裝,而FutureTask
也是一個Runnable
的實現,多這一層的目的就是爲了線程任務的返回值。
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("任務實現");
return "線程執行結果";
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<String> task = new FutureTask<>(new MyCallable());
new Thread(task).start();
String result = task.get();// 阻塞當前線程,等待返回值
System.out.println(result);
}
}
task.get()
會阻塞當前線程,直到線程任務執行完畢,可以拿到返回值,或者線程任務執行出錯,拋出異常。
至於task.get()
的阻塞原理,又是另一個問題了。