![線程各屬性縱覽](https://img2023.cnblogs.com/blog/1220983/202306/1220983-20230603114109107-477345835.png) 如上圖所示,線程有四個屬性: - 線程ID - 線程名稱 - 守護線程 - 線程優先順序 ### 1. ...
如上圖所示,線程有四個屬性:
- 線程ID
- 線程名稱
- 守護線程
- 線程優先順序
1. 線程ID
-
每個線程都有id,這個id不能修改
-
線程id會不停的自增,從1開始
-
main函數就是第一個線程,id=1
id 是操作系統用來識別各個線程的編號,具有唯一性,從下麵 java 的源碼中看到,這個線程的Id初始值是0,但是每一次生成Id的時候都是先自增的(++threadSeqNumber),所以起始值實際是1。
測試代碼:
/******
* 線程Id從1開始,JVM運行起來後,自己創建的線程的Id早已不是0
*/
public class Id {
public static void main(String[] args) {
Thread thread = new Thread();
System.out.println("主線程Id:"+Thread.currentThread().getId());
System.out.println("子線程Id:"+thread.getId());
}
}
列印結果:
以上看到主線程的id為1,可以理解,那麼為什麼我們創建的子線程id就直接為12了???
我們打斷點調試發現,在我們的子線程創建之前,JVM其實已經為我們創建了許多線程
- Signal Dispatcher是把操作系統的信號發給我們適當的程式的。
- Reference Handler是和GC相關的引用線程。
- Finalizer是負責執行Finalizer對象的方法。
2. 線程名字
(1) 預設線程名的源碼分析
- 有參構造器,指定線程名
- 無參構造器,預設為
Thread-
,後接 nextThreadNum ,這個數字為0開始,自增
(2) 手動設置線程名字 setName()
從上圖中 java 的源碼可以看到,this.name = name 是修改 java 層面的線程的名字,然後 setNativeName() 是native方法(C/C++層面給線程的名字做一個設置),但當線程啟動之後,這個C/C++層面的名字不能修改了;不過 Java 層面的線程名字還是可以修改的。為什麼當線程起來之後C/C++層面不能修改,是因為他做了一個!=0(線程的狀態)的判斷,為0時就是線程 new 出來後還沒有 start。
3. 守護線程
線程類型有兩種:守護線程、用戶線程
守護線程的作用: 給用戶線程提供服務。
用戶線程和守護線程分類的標準:這個線程是否會阻止 JVM 的退出。當還有用戶線程在執行的時候JVM是不會停止的,如果當前只剩下了守護線程,那麼守護線程會隨著JVM一起停止。
線程類型的特性:
- 線程類型預設繼承自父線程
- 通常而言,所有的守護線程都是由 JVM 啟動。在 JVM 啟動的時候有一個非守護線程,那就是main函數。
- 守護線程不影響 JVM退出,當 JVM 退出的時候,他只看有沒有用戶線程。
守護線程和用戶線程區別
- 整體上沒有區別(只是代碼的任務不一樣)
- 唯一區別在於是否影響 JVM 的退出(如果是用戶線程會影響JVM的退出,守護線程則不會)
4. 線程優先順序
Q:線程的優先順序是什麼?
A:在操作系統中,線程可以劃分優先順序,線程優先順序越高,獲得 CPU 時間片的概率就越大,但線程優先順序的高低與線程的執行順序並沒有必然聯繫,優先順序低的線程也有可能比優先順序高的線程先執行。
優先順序有10個級別,預設5,在Java源碼中有三個定義,最低,預設,最高的優先順序定義,如下圖。
線程雖然有優先順序這個設定,但是實際開發中儘量不要設置優先順序,即對程式的設計不應該依賴於優先順序,主要原因如下:
-
不同的操作系統優先順序不同
-
window
中只有7個優先順序,java 程式運行在 windows 系統時,會進行優先順序映射時,就可能會有多個優先順序映射成一個優先順序 -
linux
中所有線程優先順序會被忽略,所有線程優先順序一致
-
-
優先順序可能會被操作系統修改,即優先順序高的程式不一定被優先執行