Java併發程式設計:Java執行緒
建立和執行執行緒
- 方法一:直接使用Thread
// 建立執行緒物件
Thread t = new Thread("name") {
public void run() {
// 要執行的任務
}
};
// 啟動執行緒
t.start();
// Java 8 以後可以使用lambda精簡程式碼
Thread t = new Thread(()->{
// 要執行的程式碼
});
- 方法二:使用Runnable配合Thread
把【執行緒】與【任務】(要執行的程式碼)分開,Thread代表執行緒,Runnable可執行的任務(執行緒要執行的程式碼)
Runnable runnable = new Runnable() {
public void run() {
// 要執行的任務
}
};
// 建立執行緒物件 引數1:任務物件 引數2:執行緒名字
Thread t = new Thread(runnable, "name");
// 啟動執行緒
t.start();
- 小結
- 方法一把執行緒和任務合併在了一起,方法二是把執行緒和任務分開了
- 用Runnable更容易與執行緒池等高階API配合
- 用Runnable讓任務類脫離了Thread繼承體系,更靈活
- 方法三:FutureTask配合Thread
// 建立任務物件
FutureTask<Integer> task3 = new FutureTask<>(()->{
log.debug("hello");
return 100;
});
// 引數1 是任務物件; 引數2 是執行緒名字,推薦
new Thread(task3, "t3").start();
// 主執行緒阻塞,同步等待 task 執行完畢的結果
Integer result = task3.get();
log.debug("結果是:{}", result);
原理之執行緒執行
棧與棧幀
JVM中由堆、棧、方法區所組成,其中棧記憶體給執行緒用,每個執行緒啟動後,虛擬機器就會為其分配一塊棧記憶體。
- 每個棧由多個棧幀(Frame)組成,對應著每次方法呼叫時所佔用的記憶體
- 每個執行緒只能有一個活動棧幀,對應著當前正在執行的那個方法
執行緒上下文切換
因為以下一些原因導致CPU不再執行當前的執行緒,轉而執行另一個執行緒的程式碼:
- 被動
- 執行緒的CPU時間片用完
- 垃圾回收
- 有更高優先順序的執行緒需要執行
- 主動
- 執行緒自己呼叫了sleep、yield、wait、join、park、synchronized、lock等方法
當Context Switch發生時,需要由作業系統儲存當前執行緒的狀態,並恢復另一個執行緒的狀態,Java中對應的概念就是程式計數器(Program Counter Register), 它的作用是記住下一條jvm指令的執行地址,是執行緒私有的
- 狀態包括程式計數器、虛擬機器棧中每個棧幀的資訊,如區域性變數、運算元棧、返回地址等
- Context Switch頻繁發生會影響效能
常見方法
方法名 | static | 功能說明 | 注意 |
---|---|---|---|
start() | 啟動一個新執行緒,在新的執行緒執行 run 方法中的程式碼 | start 方法只是讓執行緒進入就緒,裡面程式碼不一定立刻執行(CPU 的時間片還沒分給它)。每個執行緒物件的start方法只能呼叫一次,如果呼叫了多次會出現IllegalThreadStateException | |
run() | 新執行緒啟動後會呼叫的方法 | 如果在構造 Thread 物件時傳遞了 Runnable 引數,則執行緒啟動後會呼叫 Runnable 中的 run 方法,否則預設不執行任何操作。但可以建立 Thread 的子類物件,來覆蓋預設行為 | |
join() | 等待執行緒執行結束 | ||
join(long n ) | 等待執行緒執行結束,最多等待 n毫秒 | ||
getId() | 獲取執行緒長整型的 id | id唯一 | |
getName() | 獲取執行緒名 | ||
setName(String) | 修改執行緒名 | ||
getPriority() | 獲取執行緒優先順序 | ||
setPriority(int) | 修改執行緒優先順序 | java中規定執行緒優先順序是1~10 的整數,較大的優先順序能提高該執行緒被 CPU 排程的機率 | |
getState() | 獲取執行緒狀態 | Java 中執行緒狀態是用 6 個 enum 表示,分別為:NEW, RUNNABLE, BLOCKED, WAITING,TIMED_WAITING, TERMINATED | |
isInterrupted() | 判斷是否被打斷 | 不會清除打斷標記 | |
isAlive() | 執行緒是否存活(還沒有執行完畢) | ||
interrupt() | 打斷執行緒 | 如果被打斷執行緒正在 sleep,wait,join 會導致被打斷的執行緒丟擲 InterruptedException,並清除 打斷標記 ;如果打斷的正在執行的執行緒,則會設定 打斷標記 ;park 的執行緒被打斷,也會設定 打斷標記 | |
interrupted() | static | 判斷當前執行緒是否被打斷 | 會清除 打斷標記 |
currentThread() | static | 獲取當前正在執行的執行緒 | |
sleep(long n) | static | 讓當前執行的執行緒休眠n毫秒,休眠時讓出 cpu的時間片給其它執行緒 | |
yield() | static | 提示執行緒排程器讓出當前執行緒對CPU的使用 | 主要是為了測試和除錯 |
Reference
相關文章
- java併發程式設計——執行緒池Java程式設計執行緒
- java併發程式設計——執行緒同步Java程式設計執行緒
- java併發程式設計 | 執行緒詳解Java程式設計執行緒
- Java併發程式設計-執行緒基礎Java程式設計執行緒
- Java併發程式設計:執行緒池ThreadPoolExecutorJava程式設計執行緒thread
- Java併發程式設計之執行緒安全、執行緒通訊Java程式設計執行緒
- Java 併發程式設計 | 執行緒池詳解Java程式設計執行緒
- java併發程式設計:執行緒池的使用Java程式設計執行緒
- 《java併發程式設計的藝術》執行緒池Java程式設計執行緒
- Java併發程式設計——深入理解執行緒池Java程式設計執行緒
- Java併發程式設計序列之執行緒狀態Java程式設計執行緒
- Java併發程式設計之執行緒篇之執行緒中斷(三)Java程式設計執行緒
- Java併發程式設計之執行緒篇之執行緒簡介(二)Java程式設計執行緒
- 好程式設計師Java培訓分享Java多執行緒併發程式設計師Java執行緒
- Java併發(一)----程式、執行緒、並行、併發Java執行緒並行
- Java併發程式設計之執行緒篇之執行緒的由來(一)Java程式設計執行緒
- Java執行緒與併發程式設計實踐----額外的執行緒能力Java執行緒程式設計
- 【架構】Java併發程式設計——執行緒池的使用架構Java程式設計執行緒
- JAVA併發程式設計:執行緒池ThreadPoolExecutor原始碼分析Java程式設計執行緒thread原始碼
- Java併發程式設計學習筆記----執行緒池Java程式設計筆記執行緒
- Java併發程式設計:Java的四種執行緒池的使用,以及自定義執行緒工廠Java程式設計執行緒
- Java併發程式設計筆記6:執行緒池的使用Java程式設計筆記執行緒
- 程式設計體系結構(05):Java多執行緒併發程式設計Java執行緒
- Java併發程式設計:執行緒和鎖的使用與解析Java程式設計執行緒
- 《java學習三》併發程式設計 -------執行緒池原理剖析Java程式設計執行緒
- Java併發程式設計實戰(5)- 執行緒生命週期Java程式設計執行緒
- Java併發程式設計(二)如何保證執行緒同時/交替執行Java程式設計執行緒
- Java併發程式設計:Java執行緒池核心ThreadPoolExecutor的使用和原理分析Java程式設計執行緒thread
- Java 多執行緒與併發程式設計 · Java 工程師必知必會Java執行緒程式設計工程師
- 併發程式設計之多執行緒執行緒安全程式設計執行緒
- JAVA多執行緒併發Java執行緒
- 併發程式設計之:執行緒程式設計執行緒
- Java併發程式設計序列之JUC中Condition執行緒通訊Java程式設計執行緒
- Java併發程式設計—synchronized保證執行緒安全的原理分析Java程式設計synchronized執行緒
- java併發程式設計JUC第九篇:CountDownLatch執行緒同步Java程式設計CountDownLatch執行緒
- Java併發(四)----執行緒執行原理Java執行緒
- 高併發程式設計系列:4種Java執行緒鎖全面詳解程式設計Java執行緒
- Java併發程式設計——深入理解執行緒間的協作方式Java程式設計執行緒