執行緒基礎與狀態
??生命不息,寫作不止
?? 繼續踏上學習之路,學之分享筆記
?? 總有一天我也能像各位大佬一樣
?? 一個有夢有戲的人 @怒放吧德德
??分享學習心得,歡迎指正,大家一起學習成長!

- 執行緒基礎與狀態
- 前言
- 執行緒的概念
- 什么是行程?
- 什么是執行緒?
- 在Java執行緒中是怎樣的呢?
- Java執行緒的Sleep、Yield、Join方法
- 1、sleep方法
- 2、Yield方法
- 3、Join方法
- Java的執行緒狀態
- 執行緒的不同狀態
- Java執行緒的狀態轉化
- Java執行緒狀態代碼
- 博文推薦
前言
好久沒堅持學習了,所以,這次要好好下定決心學習,多執行緒與高并發不是一天兩天就能弄懂的,需要不斷的學習、實踐,本次筆者將最近學習的內容知識記錄下來,多執行緒也是一項比較重要的內容,雖然CRUD不太會接觸到,但是,在一些相關場景可能會有某些問題是由于執行緒導致的,
執行緒的概念
要了解執行緒的概念,就需要知道什么是行程,簡單理解就是一個行程中包含了許多個執行緒,現在就簡單介紹,后續若是有對作業系統進行研究的話會慢慢介紹,具體關于執行緒行程的內容可以去看看王道的作業系統,里面講述得特別清楚,
什么是行程?
是系統進行資源分配的基本單位,是作業系統結構的基礎,行程是執行緒的容器,程式是指令、資料及其組織形式的描述,行程是程式的物體,
什么是執行緒?
所謂執行緒就是作業系統(OS)能夠進行運算調度的最小單位,是一個基本的CPU執行單元,也是執行程式流的最小單元,能夠提高OS的并發性能,減小程式在并發執行時所付出的時空開銷,執行緒是行程的一個物體,是被系統獨立調度和分派的基本單位,執行緒本身是不擁有系統資源的,但是它能夠使用同屬行程的其他執行緒共享行程所擁有的全部資源,
在Java執行緒中是怎樣的呢?
在Java中,最常見得就是繼承Thread類或者實作Runnable介面,再通過run或者start方法去執行執行緒,
如以下代碼,這是一段很簡單得代碼塊,通過繼承Thread類,重寫run方法來創建執行緒,并且通過run和start來運行,
public class Thread_demo01 {
private static class Thread1 extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("Thread1-" + i);
}
}
}
public static void main(String[] args) {
new Thread1().run(); // 順序執行
// new Thread1().start(); // 執行緒同時執行
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("main");
}
}
}
這兩種不同得啟動方式,出現得現象也是不同的,
- 使用run方法啟動執行緒

- 使用start方法啟動執行緒

關于這兩種方式啟動執行緒可以看一下下面的流程圖,

run方法是會讓執行緒T1先執行完畢之后,再繼續執行主執行緒,而start方法他是同時執行兩個執行緒,
Java執行緒的Sleep、Yield、Join方法
1、sleep方法
sleep()需要提供一個時間引數(毫秒),會使得執行緒在一定的時間內被暫停執行,在sleep的程序中,執行緒是不會釋放鎖的,只會進入阻塞狀態,讓出cpu給其他執行緒去執行,如下代碼演示,此處不做鎖的探究,
public class T3_Thread_Sleep {
public static void main(String[] args) {
Thread t1 = new Thread(new Thread1());
Thread t2 = new Thread(new Thread2());
t1.start();
t2.start();
}
static class Thread1 implements Runnable {
@Override
public void run() {
System.out.println("T1 is running");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("T1 is end");
}
}
static class Thread2 implements Runnable {
@Override
public void run() {
System.out.println("T2 is running");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("T2 is end");
}
}
}
運行之后在T1執行緒休眠的時候會讓出cpu資源給T2執行緒,T1執行緒會睡眠1秒,T2睡眠2秒,最終結果如圖

2、Yield方法
yield()與sleep()都是讓執行緒暫停執行,也是不會釋放鎖資源,但是yield并不是讓行程進入阻塞態,而是回到就緒態,等待重新獲取CPU資源,此時,其他的執行緒有機會獲得cpu資源,也有可能在yield方法進入就緒態后立馬變成執行態,如以下代碼,同樣不考慮鎖的問題,
public class T4_Thread_Yield {
static class Thread1 implements Runnable {
@Override
public void run() {
System.out.println("T1 is running");
Thread.yield();
System.out.println("T1 is end");
}
}
static class Thread2 implements Runnable {
@Override
public void run() {
System.out.println("T2 is running");
System.out.println("T2 is end");
}
}
public static void main(String[] args) {
Thread t1 = new Thread(new Thread1());
Thread t2 = new Thread(new Thread2());
t1.start();
t2.start();
}
}
經過不同的測驗,結果都是不同的,


3、Join方法
join()方法是暫停當前執行緒,呼叫執行另一個執行緒,等待join的執行緒執行完畢后才能夠繼續執行當前執行緒,如以下例子,T1,T2同時開始,在T2執行緒中join了T1,就會導致T1要先執行完畢之后,才會去執行T2,
public class T5_Thread_Join {
public static void main(String[] args) {
Thread T1 = new Thread(() -> {
System.out.println("T1開始");
for (int i = 0; i < 5; i++) {
System.out.println("執行緒T1執行中: " + i);
}
System.out.println("T1結束");
});
Thread T2 = new Thread(() -> {
System.out.println("T2開始");
for (int i = 0; i < 5; i++) {
System.out.println("執行緒T2執行中: " + i);
if (i == 3) {
try {
T1.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
System.out.println("T2結束");
});
T1.start();
T2.start();
}
}
結果如下,不管怎么測驗,都會是T2最后執行結束,

Java的執行緒狀態
執行緒具有最基本的三態(就緒、運行、阻塞),執行緒與行程一樣,各執行緒之間也存著共享資源和互相合作的制約關系,致使執行緒運行時具有間斷性,接下來看一下如圖,這是五種狀態的轉化,

執行緒的不同狀態
在Java執行緒中有6中狀態,從執行緒的創建到執行緒的終止,執行緒創建為NEW創建態,通過start啟動執行緒,執行緒內部會從就緒態轉成運行態,在Java執行緒中統稱為“運行態”,執行緒由于被掛起、呼叫yeild等方法能夠使執行緒從運行態轉成就緒態,也能夠通過執行緒的其他方法或者鎖阻塞執行緒,直到時間結束或者是獲得鎖等,從而回到RUNABLE狀態,
- 初始(NEW):新創建了一個執行緒物件,但還沒有呼叫start()方法,
- 運行(RUNNABLE):Java執行緒中將就緒(Ready)和運行中(Running)兩種狀態籠統的稱為“運行”,執行緒物件創建后,其他執行緒(比如main執行緒)呼叫了該物件的start()方法,該狀態的執行緒位于可運行執行緒池中,等待被執行緒調度選中,獲取CPU的使用權,此時處于就緒狀態(Ready),就緒狀態的執行緒在獲得CPU時間片后變為運行中狀態(Running),
- 阻塞(BLOCKED):表示執行緒阻塞于鎖,
- 等待(WAITING):進入該狀態的執行緒需要等待其他執行緒做出一些特定動作(通知或中斷),
- 超時等待(TIMED_WAITING):該狀態不同于WAITING,它可以在指定的時間后自行回傳,
- 終止(TERMINATED):表示該執行緒已經執行完畢,
Java執行緒的狀態轉化
如執行緒狀態轉換圖,以下就是Java執行緒狀態的轉換流程,執行緒可以通過實作Runnable介面或者繼承Threa類,然后去實體化Java的執行緒物件,在執行緒被執行之前都是屬于創建態(NEW),在呼叫start方法后,執行緒就會轉成RUNABLE狀態,在RUNABLE中,當執行緒處于就緒態(Ready)的時候,經過調度分配了cpu資源,這時轉成了運行態,當執行緒被掛起、執行緒執行了yield,執行緒將會退回就緒態,在運行態(RUNABLE),也會通過一些處理而被阻塞或者等待,終止狀態(TERMINATED)是執行緒執行完畢退出,此時,終止態的執行緒不會直接轉成創建態,

Java執行緒狀態代碼
Java中執行緒的狀態都是在java.lang.Thread.State的列舉類中,
可以看一下以下列舉代碼,分別為(NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED)六種,
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
接下來看一下演示代碼
public class T6_Thread_State {
static class Thread1 extends Thread {
@Override
public void run() {
System.out.println("run - 當前執行緒的狀態: " + this.getState());
for (int i = 0; i < 5; i++) {
try {
System.out.println("sleep前 - 當前執行緒的狀態: " + this.getState());
Thread.sleep(1000);
System.out.println("sleep后 - 當前執行緒的狀態: " + this.getState());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread1 t1 = new Thread1();
System.out.println("main - 當前執行緒的狀態: " + t1.getState());
t1.start();
System.out.println("join前 - 當前執行緒的狀態: " + t1.getState());
t1.join();
System.out.println("join后 - 當前執行緒的狀態: " + t1.getState());
}
}
運行結果,可以只管看到執行緒在運行程序種的狀態切換,

博文推薦
這里推薦給各位一篇很不錯的博客文章,是針對Java執行緒的狀態轉換的詳細介紹
-
Java執行緒的6種狀態及切換(透徹講解)_潘建南的博客-CSDN博客_執行緒的5種狀態
-
執行緒池 waiting on condition_Java執行緒生命周期與狀態切換_有所不知的博客-CSDN博客
??創作不易,如有錯誤請指正,感謝觀看!記得點贊哦!??
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/543996.html
標籤:其他
