溫馨提示:閱讀本文需要5-6分鐘(少量程式碼)
今天,我們來解決一個問題:
併發、並行傻傻分不清楚?執行緒的一生都經歷些什麼?
人生一切難題,知識給你答案。
==併發與並行==
併發是指在某個時間段內,多工交替處理的能力。並行是指同時處理多工的能力。
案例:商場銷售員需要面對多位顧客時,有的顧客問價格,有的顧客問質量,這時銷售員需要不斷的回答顧客,中間不停的切換話題並記住之前的話題,方便回過頭回答,這種方式可以理解為併發,如果有多位銷售員對應多位顧客,多位銷售員同時回答顧客問題,這種方式就是並行。
==執行緒的生命週期==
執行緒是CPU排程和分配的基本單位。執行緒可以擁有自己的操作棧、程式計數器、區域性變數表等資源,它與同一程式內的其他執行緒共享該程式的所有資源。
執行緒的建立有三種方式,第一種是繼承自Thread類,如下所示:
public class HandlerThread extends Thread {
@Override public void run() {
}
}複製程式碼
第二種方式是實現Runnable介面,如下所示:
public class HandlerThread implements Runnable {
@Override public void run() {
}
}複製程式碼
推薦使用第二種方式,因為繼承Thread類不符合里氏替換原則,實現Runnable介面可以使程式設計更加靈活,對外暴露的細節比較少。
第三種方式使用Callable介面,如下所示:
public class Demo implements Callable<
String>
{
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<
String>
callable=new Demo();
FutureTask<
String>
futureTask=new FutureTask<
>
(callable);
new Thread(futureTask).start();
System.out.println(futureTask.get());
} @Override public String call() throws Exception {
return "demo";
}
}複製程式碼
Callable和Future介面的區別在於:
- Callable規定的方法是call(),而Runnable規定的方法是run().
- Callable的任務執行後可返回值,而Runnable的任務是不能返回值的。
- call()方法可丟擲異常,而run()方法是不能丟擲異常的。
- 執行Callable任務可拿到一個Future物件, Future表示非同步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並檢索計算的結果。通過Future物件可瞭解任務執行情況,可取消任務的執行,還可獲取任務執行的結果。
- Callable是類似於Runnable的介面,實現Callable介面的類和實現Runnable的類都是可被其它執行緒執行的任務。
執行緒的生命週期有五種狀態,如下圖:
執行緒的生命週期的狀態有:新建狀態、就緒狀態、執行狀態、阻塞狀態以及終止狀態。
- new,新建狀態,是執行緒被建立且未啟動的狀態。
- Runnable,就緒狀態,是呼叫start()方法之後執行之前的狀態,start()不能被多次呼叫,否則會丟擲IllegalStateException異常。
- Running,執行狀態,是run()正在執行時執行緒的狀態。執行緒可能會由於某些因素而推出Running,如時間、異常、鎖、排程等。
- Blocked,阻塞狀態,進入此狀態的情況包括:同步阻塞(鎖被其他執行緒佔用)、主動阻塞(呼叫Thread的某些方法,主動讓出CPU執行權,比如sleep()、join()等)以及等待阻塞(執行了wait()方法)。
- Dead,終止狀態,是run()執行結束,或因異常退出後的狀態。