1 線程簡介
首先我們要清楚的是枢贿,任何程序想要實現(xiàn)線程都需要內(nèi)核線程的支持,至少要有一個楣黍,不然程序無法執(zhí)行斋配。用戶線程和內(nèi)核線程的比例(M:N)體現(xiàn)了線程的不同實現(xiàn)方式戏锹。而對于高版本的Java(1.3及以后版本)盗似,一個Java的Thread就對應(yīng)一個操作系統(tǒng)的線程俺亮。
/**
* 可以創(chuàng)建多個線程
* <p>
* 每個線程都有優(yōu)先級绳矩。
* 指優(yōu)先級越高罩润,越有可能先執(zhí)行。因為高優(yōu)先級的擁有更多資源翼馆,更容易搶到CPU資源而已割以。
* 線程優(yōu)先級有繼承效果,比如main線程創(chuàng)建了線程A,則線程A初始優(yōu)先級繼承main的優(yōu)先級应媚,但是還可以修改為其他優(yōu)先級严沥。
* <p>
* 線程分為用戶線程和守護線程。
* 用戶線程執(zhí)行完之后中姜,不管守護線程有沒有執(zhí)行完消玄,jvm都會關(guān)閉
* 守護線程A創(chuàng)建的線程B也是守護線程跟伏,但是守護線程B在未執(zhí)行之前可以設(shè)置為非守護線程
* setDemon()方法當(dāng)線程開始之后就不可以設(shè)置了
* if (isAlive()) {
* throw new IllegalThreadStateException();
* }
* <p>
* 創(chuàng)建線程 1 :繼承Thread類
* 創(chuàng)建線程 2 :實現(xiàn)Runnable接口
* 創(chuàng)建線程 1 :實現(xiàn)Callable<>接口 通過FuntureTask(Callable<> caller) 實現(xiàn),
* 本質(zhì)上還是第二種方式翩瓜,因為FutureTask實現(xiàn)了 Runnable接口
* <p>
* The following code would then create a thread and start it running:
* <blockquote><pre>
* PrimeRun p = new PrimeRun(143);
* new Thread(p).start();
* </pre></blockquote>
* <p>
* 每個線程的名稱都是不同的受扳,如果存在相同的線程名稱,會將設(shè)置相同名字的后一個線程重新生成名稱
* <p>
*/
public class Thread implements Runnable {
/**
* 初始化本地方法兔跌,(native方法) 當(dāng)執(zhí)行時不需要再去類庫加載勘高,提升性能 靜態(tài)方法,類級別的
* 可以理解成為本類的本地方法 提前注冊進來 提升執(zhí)行時的性能
* 都是靜態(tài)的坟桅,類裝載時執(zhí)行
*/
private static native void registerNatives();
static {
registerNatives();
}
}
2 線程上下文
CPU在一個時刻只能運行一個線程华望,當(dāng)在運行一個線程的過程中轉(zhuǎn)去運行另外一個線程,這個叫做線程上下文切換(對于進程也是類似)桦卒。
由于可能當(dāng)前線程的任務(wù)并沒有執(zhí)行完畢立美,所以在切換時需要保存線程的運行狀態(tài),以便下次重新切換回來時能夠繼續(xù)切換之前的狀態(tài)運行方灾。舉個栗子:線程A正在讀取文件建蹄,當(dāng)讀到一半時需要暫停線程A,轉(zhuǎn)去執(zhí)行線程B裕偿,當(dāng)再次切換回來執(zhí)行線程A的時候洞慎,我們不希望線程A又從文件的開頭來讀取。因此需要記錄線程A的運行狀態(tài)和執(zhí)行位置等嘿棘,那么會記錄哪些數(shù)據(jù)呢劲腿?因為下次恢復(fù)時需要知道在這之前當(dāng)前線程已經(jīng)執(zhí)行到哪條指令了,所以需要記錄程序計數(shù)器的值鸟妙,另外比如說線程正在進行某個計算的時候被掛起了焦人,那么下次繼續(xù)執(zhí)行的時候需要知道之前掛起時變量的值時多少,因此需要記錄CPU寄存器的狀態(tài)重父。所以一般來說花椭,線程上下文切換過程中會記錄程序計數(shù)器、CPU寄存器狀態(tài)等數(shù)據(jù)房午。
對于線程的上下文切換實際上就是 存儲和恢復(fù)CPU狀態(tài)的過程矿辽,它使得線程執(zhí)行能夠從中斷點恢復(fù)執(zhí)行。
雖然多線程可以使得任務(wù)執(zhí)行的效率得到提升郭厌,但是由于在線程切換時同樣會帶來一定的開銷代價袋倔,并且多個線程會導(dǎo)致系統(tǒng)資源占用的增加,所以在進行多線程編程時要注意這些因素折柠。
3 線程參數(shù)
private volatile String name; //線程名稱
private int priority; //線程優(yōu)先級
private Thread threadQ; //暫時不知道是干什么的宾娜,請教各位大佬 (感覺和JVM有關(guān))
private long eetop; //JVM中的JavaThread指針
private boolean single_step;//字面意思 是否單步執(zhí)行 請教各位大佬具體細節(jié)(感覺和JVM有關(guān))
private boolean daemon = false; //是否是守護線程,默認false
private boolean stillborn = false; //字面意思 夭折 請教各位大佬具體細節(jié)(感覺和JVM state有關(guān))
private Runnable target; //指定運行其中的Runnable扇售,一般都需要指定碳默,不指定的線程沒有意義贾陷,或者可以通過創(chuàng)建Thread的子類并重新run方法缘眶。
private ThreadGroup group; //指定當(dāng)前線程的線程組嘱根,未指定時線程組為創(chuàng)建該線程所屬的線程組。線程組可以用來管理一組線程巷懈,通過activeCount() 來查看活動線程的數(shù)量该抒。感覺除了這個沒有什么大的用處。如果有其他用處或理解歡迎留言
private ClassLoader contextClassLoader; //線程用的上下文類加載器顶燕,該上下文類加載器可供線程加載類和資源
private AccessControlContext inheritedAccessControlContext; //繼承的訪問系統(tǒng)資源的上下文(本線程的)
private static int threadInitNumber;//計數(shù)變量凑保,用在nextThreadNum方法中為匿名線程生成名稱
ThreadLocal.ThreadLocalMap threadLocals = null; //線程局部變量
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; //可繼承的線程局部變量 比如一些 logId uid token 什么項目中共用的一些參數(shù)及標(biāo)準 如果{true},則從構(gòu)造線程 繼承(inheritableThreadLocals) 的初始值 public的構(gòu)造器 此參數(shù)均為true
private long stackSize;// 新線程預(yù)期所需的堆棧大小涌攻,或者零表示該參數(shù)將被忽略欧引。與平臺相關(guān),不建議使用該屬性恳谎。
private long nativeParkEventPointer;//native線程終止后芝此,保持虛擬機私有狀態(tài)
private long tid;//線程id
private static long threadSeqNumber;//為了生成線程ID
private volatile int threadStatus = 0; // java線程狀態(tài),已初始化因痛,0代表'not yet started'
volatile Object parkBlocker; //LockSupport.park是提供給當(dāng)前調(diào)用的參數(shù),由 LockSupport.setBlocker 設(shè)置,通過LockSupport.getBlocker訪問
private volatile Interruptible blocker;//此線程在 可中斷I/O操作中 被阻塞的對象(如果有)婚苹。設(shè)置此線程的中斷狀態(tài)后,應(yīng)調(diào)用 該對象的中斷方法鸵膏。
private final Object blockerLock = new Object();
4 線程優(yōu)先級
1.java線程是通過映射到系統(tǒng)的原生線程上來實現(xiàn)的膊升,所以線程的調(diào)度最終還是取決于操作系統(tǒng),操作系統(tǒng)的優(yōu)先級與java的優(yōu)先級并不一一對應(yīng)谭企,如果操作系統(tǒng)的優(yōu)先級級數(shù)大于java的優(yōu)先級級數(shù)(10級)還好廓译,但是如果小于得的話就不行了,這樣會導(dǎo)致不同優(yōu)先級的線程的優(yōu)先級是一樣的债查。
2.優(yōu)先級可能會被系統(tǒng)自動改變非区,比如windows系統(tǒng)中就存在一個優(yōu)先級推進器,大致功能就是如果一個線程執(zhí)行的次數(shù)過多的話攀操,可能會越過優(yōu)先級為他分配執(zhí)行時間
3.線程的調(diào)度最終還是取決于操作系統(tǒng)中的線程規(guī)劃器院仿。其實,即使設(shè)置了線程的優(yōu)先級速和,一樣無法確保這個線程一定先執(zhí)行歹垫,因為它有很大的隨機性。它并無法控制執(zhí)行哪個線程颠放,因為線程的執(zhí)行排惨,是搶占資源后才能執(zhí)行的操作,而搶點資源時碰凶,最多是給于線程優(yōu)先級較高的線程一點機會而已暮芭,能不能抓住可是不一定的鹿驼。
說到底就一句話:線程優(yōu)化級較高的線程不一定先執(zhí)行。
5 線程狀態(tài)
線程內(nèi)部枚舉有6種狀態(tài):NEW辕宏、RUNNABLE畜晰、BLOCKED、WAITING瑞筐、TIMED_WAITING凄鼻、TERMINATED
NEW:新生;尚未啟動的線程的線程狀態(tài)
RUNNABLE:可運行聚假; 可運行線程的線程狀態(tài)块蚌。
處于可運行狀態(tài)的線程正在Java虛擬機中執(zhí)行,但可能需要等待其他資源調(diào)度膘格,如CPU峭范。
BLOCKED:阻塞;處于阻塞狀態(tài)的線程正在等待鎖瘪贱。BLOCKED 狀態(tài)可以視作是一種特殊的 WAITING纱控,特指等待鎖。
BLOCKED 源碼注釋:
1.一個處于 blocked 狀態(tài)的線程正在等待一個監(jiān)視器鎖以進入一個同步的塊或方法政敢。
A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method or
2.或在其調(diào)用 Object.wait 方法之后其徙,以再次進入一個同步的塊或方法。
reenter a synchronized block/method after calling Object.wait
第一句:本線程在等待其他線程釋放鎖喷户,獲得鎖之后才能執(zhí)行后面鎖住的代碼塊或者方法唾那。
第二句:本線程持有鎖,內(nèi)部調(diào)用 Object.wait 方法進入阻塞狀態(tài)褪尝,這時會釋放鎖闹获,等待其他線程 Object.notify方法將本線程喚醒,喚醒后需要重新獲取到鎖才能繼續(xù)執(zhí)行后面的代碼塊河哑”芊蹋可以看出以下幾點:
1.必須持有該鎖才能調(diào)用該鎖的 wait 方法,這是第一次 enter璃谨。
2.調(diào)用 wait 之后線程會釋放該鎖沙庐,并進入該鎖的等待隊列(wait set)中,狀態(tài)變?yōu)閃AITING佳吞。
3.當(dāng)收到其它線程對該鎖的 notify 或 notifyAll 通知之后拱雏,等待線程并不能立即恢復(fù)執(zhí)行,因為停止的地方是在同步塊內(nèi)底扳,而鎖已經(jīng)釋放了铸抑,所以它要重新獲取鎖才能再次執(zhí)行后續(xù)的同步塊reenter。這是第二次 enter衷模,所以叫 reenter鹊汛。
4.但是該線程還是要與其它線程去競爭鎖蒲赂,這一過程跟 enter 的過程一樣,因此也會因為鎖已經(jīng)被其它線程據(jù)有而導(dǎo)致 BLOCKED刁憋。
WAITING:等待滥嘴;一個正在無限期等待其他線程執(zhí)行完成處于這一狀態(tài),他和BLOCKED區(qū)別在于需不需要等待鎖职祷。
TIMED_WAITING:持續(xù)時間等待氏涩,有限期的等待;
TERMINATED:結(jié)束有梆。
6 線程方法
Thread Thread.currentThread() //獲得當(dāng)前線程的引用。
boolean isAlive() //測試線程是否處于活動狀態(tài)意系。
void setDaemon(boolean on) //設(shè)置線程是否為守護線程
boolean isDaemon() //測試線程是否為守護線程泥耀。
void checkAccess() //判斷當(dāng)前運行的線程是否有權(quán)修改該線程。
int Thread.activeCount()//當(dāng)前線程所在線程組中活動線程的數(shù)目蛔添。
StackTraceElement[] getStackTrace() //獲取堆棧數(shù)組痰催。
void dumpStack() //打印堆棧。
int enumerate(Thread[] tarray) //將當(dāng)前線程的線程組及其子組中的每一個活動線程復(fù)制到指定的數(shù)組中迎瞧。
Map<Thread,StackTraceElement[]> getAllStackTraces() //返回所有活動線程的堆棧跟蹤的一個映射夸溶。
boolean holdsLock(Object obj) //當(dāng)且僅當(dāng)當(dāng)前線程在指定的對象上保持監(jiān)視器鎖時,才返回 true凶硅。
void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) //設(shè)置由于未捕獲到異常導(dǎo)致線程終止時所調(diào)用的默認處理程序缝裁。
Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() //返回線程由于未捕獲到異常而突然終止時調(diào)用的默認處理程序。
Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() //返回該線程由于未捕獲到異常而突然終止時調(diào)用的處理程序足绅。
void interrupt() //中斷線程捷绑。
boolean isInterrupted()//測試線程是否已經(jīng)中斷。
boolean interrupted() //測試當(dāng)前線程是否已經(jīng)中斷氢妈。
void sleep(long millis) //休眠指定時間
void sleep(long millis, int nanos) //休眠指定時間
void yield() //釋放cpu資源進入就緒狀態(tài)重新爭搶資源粹污。意義不太大
void join() //等待該線程終止。(內(nèi)部也依賴的wait方法)
void join(long millis) //等待該線程終止的時間最長為 millis 毫秒首量。
void join(long millis, int nanos) //等待該線程終止的時間最長為 millis 毫秒 + nanos 納秒壮吩。
void setContextClassLoader(ClassLoader cl) //設(shè)置該線程的上下文 ClassLoader。
void start()//使該線程開始執(zhí)行加缘;Java 虛擬機調(diào)用該線程的 run 方法鸭叙。
void run() //線程啟動后執(zhí)行的方法。
比較重要的方法
/**
* 使線程進入就緒狀態(tài)生百,等競爭到CPU資源后執(zhí)行下面的run()方法
*
* @throws IllegalThreadStateException 線程啟動后再次調(diào)用會報錯
*/
public synchronized void start() {
/**
* VM創(chuàng)建的線程或者系統(tǒng)線程組創(chuàng)建的線程 不是通過此方法創(chuàng)建的. 該方法邏輯可能會變化.
*/
//0是就緒狀態(tài) 已經(jīng)是就緒狀態(tài),再調(diào)用此方法后就會報錯
if (threadStatus != 0) throw new IllegalThreadStateException();
//通知線程組 該線程將要啟動
group.add(this);
boolean started = false;
try {
//native方法递雀,通過虛擬機啟動線程
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
//什么也不做。防止覆蓋start0拋出的異常蚀浆,讓該異常向上傳遞
}
}
}
/**
* 爭搶到CPU資源 線程真正執(zhí)行的方法
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
/**
* 中斷此線程.
*/
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
interrupt0();
}
/**
* 測試當(dāng)前線程是否已被中斷缀程。并且清除線程的 中斷狀態(tài)
* 當(dāng)前線程已被中斷 返回true 并且清除線程的 中斷狀態(tài)(置為false)
*/
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
/**
* 測試當(dāng)前線程是否已被中斷搜吧。 和上面方法差別是該方法 不清除線程的中斷狀態(tài)
* 當(dāng)前線程已被中斷 返回true
*/
public boolean isInterrupted() {
return isInterrupted(false);
}
/**
* private 測試當(dāng)前線程是否已被中斷 根據(jù)參數(shù)看是否需要清楚中斷狀態(tài)
*/
private native boolean isInterrupted(boolean ClearInterrupted);
Thread.sleep(1000); 與 Thread.currentThread().sleep(1000); 等價,都是在何處調(diào)用杨凑,就會使得當(dāng)前的線程進入休眠狀態(tài)滤奈, main線程調(diào)用threadB.sleep(1000)與調(diào)用Thread.sleep(1000)一樣,都是使main線程休眠1000毫秒撩满,而不是使threadB休眠蜒程。
sleep方法不會釋放鎖。因為不強制需要鎖
sleep()支持中斷伺帘,因此當(dāng)檢測到中斷信號(isInterrupt=1)時昭躺,會拋出InterruptedException 異常,因此在cache塊中可以對如果發(fā)生中斷進行某些操作伪嫁。通過isInterrupted()可以發(fā)現(xiàn):在拋出異常的時候领炫,還讓異常狀態(tài)重新置為了false(isInterrupt=0)。
需要注意:由于不允許不同的線程之間的異常溢出张咳,因此在run方法中就必須對此處拋出的InterruptedException異常進行處理帝洪,因此上述示例代碼,直接對異常進行了捕捉脚猾。若是在其他的普通方法中葱峡,除非是線程需要退出,否則都不應(yīng)當(dāng)直接將異常生吞龙助。此時可以選擇:1.不捕捉 InterruptedException砰奕,將它傳播給調(diào)用者;2.捕捉InterruptedException執(zhí)行必要的清理操作泌参,重新向上拋出InterruptedException異常脆淹;3.捕捉 InterruptedException 后重新恢復(fù)中斷狀態(tài)。
6 其他
創(chuàng)建線程:1Runnable接口沽一,2.繼承Thread類盖溺,實際上也是實現(xiàn)Runnable接口,3.Callable/Future 4.線程池
實際應(yīng)用:
1铣缠、后臺任務(wù)烘嘱,例如:文件跑批,文件導(dǎo)出蝗蛙,定時百萬用戶推送消息蝇庭;
2、異步處理捡硅,例如:多線程異步處理哮内,提高程序響應(yīng);記錄日志;Tomcat內(nèi)部分發(fā)請求北发;BIO模型優(yōu)化:
Socket socket = socket.accept();//阻塞纹因,連接阻塞
New Thread(new Handler(socket)).start();//解決了r/w阻塞問題
3、分布式計算
Thread類源碼
/**
* 可以創(chuàng)建多個線程
* <p>
* 每個線程都有優(yōu)先級琳拨。
* 指優(yōu)先級越高瞭恰,越有可能先執(zhí)行。因為高優(yōu)先級的擁有更多資源狱庇,更容易搶到CPU資源而已惊畏。
* 線程優(yōu)先級有繼承效果,比如main線程創(chuàng)建了線程A,則線程A初始優(yōu)先級繼承main的優(yōu)先級密任,但是還可以修改為其他優(yōu)先級颜启。
* <p>
* 線程分為用戶線程和守護線程。
* 用戶線程執(zhí)行完之后批什,不管守護線程有沒有執(zhí)行完农曲,jvm都會關(guān)閉
* 守護線程A創(chuàng)建的線程B也是守護線程,但是守護線程B在未執(zhí)行之前可以設(shè)置為非守護線程
* setDemon()方法當(dāng)線程開始之后就不可以設(shè)置了
* if (isAlive()) {
* throw new IllegalThreadStateException();
* }
* <p>
* 創(chuàng)建線程 1 //繼承Thread類
* 創(chuàng)建線程 2 //實現(xiàn)Runnable接口
* 創(chuàng)建線程 1 //實現(xiàn)Callable<>接口 通過FuntureTask(Callable<> caller) 實現(xiàn)驻债,
* 本質(zhì)上還是第二種方式,因為FutureTask實現(xiàn)了 Runnable接口
* <p>
* The following code would then create a thread and start it running:
* <blockquote><pre>
* PrimeRun p = new PrimeRun(143);
* new Thread(p).start();
* </pre></blockquote>
* <p>
* 每個線程的名稱都是不同的形葬,如果存在相同的線程名稱合呐,會將設(shè)置相同名字的后一個線程重新生成名稱
* <p>
*/
public class Thread implements Runnable {
/**
* 初始化本地方法,(native方法) 當(dāng)執(zhí)行時不需要再去類庫加載笙以,提升性能 靜態(tài)方法淌实,類級別的
* 可以理解成為本類的本地方法 提前注冊進來 提升執(zhí)行時的性能
* 都是靜態(tài)的,類裝載時執(zhí)行
*/
private static native void registerNatives();
static {
registerNatives();
}
private volatile String name; //線程名稱
private int priority; //線程優(yōu)先級
private Thread threadQ; //暫時不知道是干什么的猖腕,請教各位大佬 (感覺和JVM有關(guān))
private long eetop; //JVM中的JavaThread指針
private boolean single_step;//字面意思 是否單步執(zhí)行 請教各位大佬具體細節(jié)(感覺和JVM有關(guān))
private boolean daemon = false; //是否是守護線程拆祈,默認false
private boolean stillborn = false; //字面意思 夭折 請教各位大佬具體細節(jié)(感覺和JVM state有關(guān))
/**
* 指定運行其中的Runnable,一般都需要指定倘感,不指定的線程沒有意義放坏,或者可以通過創(chuàng)建Thread的子類并重新run方法。
*/
private Runnable target;
/**
* 指定當(dāng)前線程的線程組老玛,未指定時線程組為創(chuàng)建該線程所屬的線程組淤年。
* 線程組可以用來管理一組線程,通過activeCount() 來查看活動線程的數(shù)量蜡豹。感覺除了這個沒有什么大的用處麸粮。
* 如果有其他用處或理解歡迎留言
*/
private ThreadGroup group;
/**
* 線程用的上下文類加載器,該上下文類加載器可供線程加載類和資源
*/
private ClassLoader contextClassLoader;
/**
* 繼承的訪問系統(tǒng)資源的上下文(本線程的)
*/
private AccessControlContext inheritedAccessControlContext;
/**
* 計數(shù)變量镜廉,用在nextThreadNum方法中為匿名線程生成名稱
*/
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
/**
* 線程局部變量
*/
ThreadLocal.ThreadLocalMap threadLocals = null;
/**
* 可繼承的線程局部變量 比如一些 logId uid token 什么項目中共用的一些參數(shù)及標(biāo)準
* 如果{true}弄诲,則從構(gòu)造線程 繼承 (inheritableThreadLocals) 的初始值
* public的構(gòu)造器 此參數(shù)均為true
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
/**
* 新線程預(yù)期所需的堆棧大小,或者零表示該參數(shù)將被忽略娇唯。
* 與平臺相關(guān)齐遵,不建議使用該屬性寂玲。
*/
private long stackSize;
private long nativeParkEventPointer;//native線程終止后,保持虛擬機私有狀態(tài)
private long tid;//線程id
private static long threadSeqNumber;//為了生成線程ID
/**
* java線程狀態(tài)洛搀,已初始化敢茁,0代表'not yet started'
*/
private volatile int threadStatus = 0;
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
/**
* java.util.concurrent.locks.LockSupport.park.是提供給當(dāng)前調(diào)用的參數(shù)
* 由 java.util.concurrent.locks.LockSupport.setBlocker 設(shè)置
* 通過 java.util.concurrent.locks.LockSupport.getBlocker訪問
*/
volatile Object parkBlocker;
/**
* 此線程在 可中斷I/O操作中 被阻塞的對象(如果有)。
* 設(shè)置此線程的中斷狀態(tài)后留美,應(yīng)調(diào)用 該對象的中斷方法彰檬。
*/
private volatile Interruptible blocker;
private final Object blockerLock = new Object();
/* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
*/
void blockedOn(Interruptible b) {
synchronized (blockerLock) {
blocker = b;
}
}
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;
/**
* 返回 當(dāng)前正在執(zhí)行的線程
*/
public static native Thread currentThread();
/**
* 向調(diào)度程序提示當(dāng)前線程愿意讓步,即讓出CPU資源和其他線程重新競爭資源
* 感覺沒什么用(主動用的情況很少)
*/
public static native void yield();
/**
* 使線程睡眠一段時間,線程掛起谎砾,讓出CPU資源
* 不會釋放鎖逢倍,因為此操作不依賴加鎖 (有鎖的話是使用者自己主觀意愿,所以需要使用者自己操作釋放鎖)
*
* @throws InterruptedException 睡眠中的線程被中斷會拋出該異常景图,該異常會清除中斷位的狀態(tài)
*/
public static native void sleep(long millis) throws InterruptedException;
public static void sleep(long millis, int nanos)
throws InterruptedException {
if (millis < 0) throw new IllegalArgumentException("timeout value is negative");
if (nanos < 0 || nanos > 999999) throw new IllegalArgumentException("nanosecond timeout value out of range");
if (nanos >= 500000 || (nanos != 0 && millis == 0)) millis++;
sleep(millis);
}
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
init(g, target, name, stackSize, null, true);
}
/**
* 使用當(dāng)前的AccessControlContext初始化線程较雕。
*/
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
if (name == null) throw new NullPointerException("name cannot be null");
this.name = name;
Thread parent = currentThread();
//獲取系統(tǒng)安全接口
SecurityManager security = System.getSecurityManager();
if (g == null) {
//如果有系統(tǒng)安全manager,從manager中獲取當(dāng)前線程的線程組挚币。
if (security != null) g = security.getThreadGroup();
//如果線程組為空亮蒋,采用父類的線程組
if (g == null) g = parent.getThreadGroup();
}
//校驗是否可以訪問
g.checkAccess();
//校驗是否允許
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
//增加線程組中未啟動線程的數(shù)量。
// 未啟動的線程不會添加到線程組中妆毕,這樣即使從未啟動過的線程也不會被收集慎玖,
// 但是必須對它們進行計數(shù),以便不會破壞其中未啟動的線程的守護程序線程組笛粘。
g.addUnstarted();
//賦值
this.group = g;
//初始守護狀態(tài)繼承父類 后面可以主動修改
this.daemon = parent.isDaemon();
//初始優(yōu)先級繼承父類 后面可以主動修改
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
//主動修改 優(yōu)先級
setPriority(priority);
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
//true時繼承父類 共用參數(shù)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
this.stackSize = stackSize;
//賦值tid
tid = nextThreadID();
}
/**
* 拋出CloneNotSupportedException趁怔,因為無法有意義地通過克隆構(gòu)造一個新的線程。
*/
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
Thread(Runnable target, AccessControlContext acc) {
init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
}
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
public Thread(String name) {
init(null, null, name, 0);
}
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
init(group, target, name, stackSize);
}
/**
* 使線程進入就緒狀態(tài)薪前,等競爭到CPU資源后執(zhí)行下面的run()方法
*
* @throws IllegalThreadStateException 線程啟動后再次調(diào)用會報錯
*/
public synchronized void start() {
/**
* VM創(chuàng)建的線程或者系統(tǒng)線程組創(chuàng)建的線程 不是通過此方法創(chuàng)建的. 該方法邏輯可能會變化.
*/
//0是就緒狀態(tài) 已經(jīng)是就緒狀態(tài),再調(diào)用此方法后就會報錯
if (threadStatus != 0) throw new IllegalThreadStateException();
//通知線程組 該線程將要啟動
group.add(this);
boolean started = false;
try {
//native方法润努,通過虛擬機啟動線程
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
//什么也不做。防止覆蓋start0拋出的異常示括,讓該異常向上傳遞
}
}
}
private native void start0();
/**
* 爭搶到CPU資源 線程真正執(zhí)行的方法
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
/**
* 系統(tǒng)調(diào)用此方法铺浇,使線程有機會在線程實際退出之前進行清理。
*/
private void exit() {
if (group != null) {
group.threadTerminated(this);
group = null;
}
target = null;
threadLocals = null;
inheritableThreadLocals = null;
inheritedAccessControlContext = null;
blocker = null;
uncaughtExceptionHandler = null;
}
/**
* 強制退出 (類比 kill -9) 過期方法 已經(jīng)不建議使用
*/
@Deprecated
public final void stop() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
checkAccess();
if (this != Thread.currentThread()) {
security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
}
}
// A zero status value corresponds to "NEW", it can't change to
// not-NEW because we hold the lock.
if (threadStatus != 0) {
resume(); // Wake up thread if it was suspended; no-op otherwise
}
// The VM can handle all thread states
stop0(new ThreadDeath());
}
@Deprecated
public final synchronized void stop(Throwable obj) {
throw new UnsupportedOperationException();
}
/**
* 中斷此線程.
*/
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
interrupt0();
}
/**
* 測試當(dāng)前線程是否已被中斷例诀。并且清除線程的 中斷狀態(tài)
* 當(dāng)前線程已被中斷 返回true 并且清除線程的 中斷狀態(tài)(置為false)
*/
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
/**
* 測試當(dāng)前線程是否已被中斷随抠。 和上面方法差別是該方法 不清除線程的中斷狀態(tài)
* 當(dāng)前線程已被中斷 返回true
*/
public boolean isInterrupted() {
return isInterrupted(false);
}
/**
* private 測試當(dāng)前線程是否已被中斷 根據(jù)參數(shù)看是否需要清楚中斷狀態(tài)
*/
private native boolean isInterrupted(boolean ClearInterrupted);
@Deprecated
public void destroy() {
throw new NoSuchMethodError();
}
/**
* 測試線程是否存活
*/
public final native boolean isAlive();
/**
* 掛起這個線程
*/
@Deprecated
public final void suspend() {
checkAccess();
suspend0();
}
/**
* 恢復(fù)掛起的線程
*/
@Deprecated
public final void resume() {
checkAccess();
resume0();
}
/**
* 設(shè)置線程優(yōu)先級
*/
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if ((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}
}
/**
* 獲取線程優(yōu)先級
*/
public final int getPriority() {
return priority;
}
public final synchronized void setName(String name) {
checkAccess();
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
if (threadStatus != 0) {
setNativeName(name);
}
}
public final String getName() {
return name;
}
public final ThreadGroup getThreadGroup() {
return group;
}
/**
* 返回線程組中活動線程數(shù)的估計值 是估計值的原因是線程調(diào)用了start之后就算在估計值中 并不一定正在執(zhí)行
*/
public static int activeCount() {
return currentThread().getThreadGroup().activeCount();
}
/**
* 將當(dāng)前線程的線程組及其子組中的每個活動線程復(fù)制到指定的數(shù)組中
*/
public static int enumerate(Thread tarray[]) {
return currentThread().getThreadGroup().enumerate(tarray);
}
/**
* 線程必須被掛起 然后計算此線程中的堆棧幀數(shù)并返回。
*/
@Deprecated
public native int countStackFrames();
/**
* 最多等待多少時間 使該線程結(jié)束
*/
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
public final synchronized void join(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
join(millis);
}
/**
* 等待線程執(zhí)行完
*/
public final void join() throws InterruptedException {
join(0);
}
public static void dumpStack() {
new Exception("Stack trace").printStackTrace();
}
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}
public final boolean isDaemon() {
return daemon;
}
public final void checkAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkAccess(this);
}
}
public String toString() {
ThreadGroup group = getThreadGroup();
if (group != null) {
return "Thread[" + getName() + "," + getPriority() + "," +
group.getName() + "]";
} else {
return "Thread[" + getName() + "," + getPriority() + "," +
"" + "]";
}
}
@CallerSensitive
public ClassLoader getContextClassLoader() {
if (contextClassLoader == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(contextClassLoader,
Reflection.getCallerClass());
}
return contextClassLoader;
}
public void setContextClassLoader(ClassLoader cl) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
}
contextClassLoader = cl;
}
/**
* 當(dāng)且僅當(dāng) 當(dāng)前線程 持有入?yún)㈡i時繁涂,才返回 true
*/
public static native boolean holdsLock(Object obj);
private static final StackTraceElement[] EMPTY_STACK_TRACE
= new StackTraceElement[0];
public StackTraceElement[] getStackTrace() {
if (this != Thread.currentThread()) {
// check for getStackTrace permission
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(
SecurityConstants.GET_STACK_TRACE_PERMISSION);
}
// optimization so we do not call into the vm for threads that
// have not yet started or have terminated
if (!isAlive()) {
return EMPTY_STACK_TRACE;
}
StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[]{this});
StackTraceElement[] stackTrace = stackTraceArray[0];
// a thread that was alive during the previous isAlive call may have
// since terminated, therefore not having a stacktrace.
if (stackTrace == null) {
stackTrace = EMPTY_STACK_TRACE;
}
return stackTrace;
} else {
// Don't need JVM help for current thread
return (new Exception()).getStackTrace();
}
}
public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
// check for getStackTrace permission
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(
SecurityConstants.GET_STACK_TRACE_PERMISSION);
security.checkPermission(
SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
}
// Get a snapshot of the list of all threads
Thread[] threads = getThreads();
StackTraceElement[][] traces = dumpThreads(threads);
Map<Thread, StackTraceElement[]> m = new HashMap<>(threads.length);
for (int i = 0; i < threads.length; i++) {
StackTraceElement[] stackTrace = traces[i];
if (stackTrace != null) {
m.put(threads[i], stackTrace);
}
// else terminated so we don't put it in the map
}
return m;
}
private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION =
new RuntimePermission("enableContextClassLoaderOverride");
private static class Caches {
static final ConcurrentMap<WeakClassKey, Boolean> subclassAudits =
new ConcurrentHashMap<>();
static final ReferenceQueue<Class<?>> subclassAuditsQueue =
new ReferenceQueue<>();
}
private static boolean isCCLOverridden(Class<?> cl) {
if (cl == Thread.class)
return false;
processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
Boolean result = Caches.subclassAudits.get(key);
if (result == null) {
result = Boolean.valueOf(auditSubclass(cl));
Caches.subclassAudits.putIfAbsent(key, result);
}
return result.booleanValue();
}
private static boolean auditSubclass(final Class<?> subcl) {
Boolean result = AccessController.doPrivileged(
new PrivilegedAction<Boolean>() {
public Boolean run() {
for (Class<?> cl = subcl;
cl != Thread.class;
cl = cl.getSuperclass()) {
try {
cl.getDeclaredMethod("getContextClassLoader", new Class<?>[0]);
return Boolean.TRUE;
} catch (NoSuchMethodException ex) {
}
try {
Class<?>[] params = {ClassLoader.class};
cl.getDeclaredMethod("setContextClassLoader", params);
return Boolean.TRUE;
} catch (NoSuchMethodException ex) {
}
}
return Boolean.FALSE;
}
}
);
return result.booleanValue();
}
private native static StackTraceElement[][] dumpThreads(Thread[] threads);
private native static Thread[] getThreads();
public long getId() {
return tid;
}
/**
* NEW:A thread that has not yet started is in this state.
* RUNNABLE:A thread executing in the Java virtual machine is in this state.
* BLOCKED:A thread that is blocked waiting for a monitor lock is in this state.
* WAITING:A thread that is waiting indefinitely for another thread to perform a particular action is in this state.
* TIMED_WAITING:A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
* TERMINATED:A thread that has exited is in this state.
*/
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
public State getState() {
// get current thread state
return sun.misc.VM.toThreadState(threadStatus);
}
@FunctionalInterface
public interface UncaughtExceptionHandler {
/**
* Method invoked when the given thread terminates due to the
* given uncaught exception.
* <p>Any exception thrown by this method will be ignored by the
* Java Virtual Machine.
*
* @param t the thread
* @param e the exception
*/
void uncaughtException(Thread t, Throwable e);
}
private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(
new RuntimePermission("setDefaultUncaughtExceptionHandler")
);
}
defaultUncaughtExceptionHandler = eh;
}
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
return defaultUncaughtExceptionHandler;
}
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
return uncaughtExceptionHandler != null ?
uncaughtExceptionHandler : group;
}
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
checkAccess();
uncaughtExceptionHandler = eh;
}
private void dispatchUncaughtException(Throwable e) {
getUncaughtExceptionHandler().uncaughtException(this, e);
}
static void processQueue(ReferenceQueue<Class<?>> queue,
ConcurrentMap<? extends
WeakReference<Class<?>>, ?> map) {
Reference<? extends Class<?>> ref;
while ((ref = queue.poll()) != null) {
map.remove(ref);
}
}
static class WeakClassKey extends WeakReference<Class<?>> {
/**
* saved value of the referent's identity hash code, to maintain
* a consistent hash code after the referent has been cleared
*/
private final int hash;
/**
* Create a new WeakClassKey to the given object, registered
* with a queue.
*/
WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
super(cl, refQueue);
hash = System.identityHashCode(cl);
}
/**
* Returns the identity hash code of the original referent.
*/
@Override
public int hashCode() {
return hash;
}
/**
* Returns true if the given object is this identical
* WeakClassKey instance, or, if this object's referent has not
* been cleared, if the given object is another WeakClassKey
* instance with the identical non-null referent as this one.
*/
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj instanceof WeakClassKey) {
Object referent = get();
return (referent != null) &&
(referent == ((WeakClassKey) obj).get());
} else {
return false;
}
}
}
@sun.misc.Contended("tlr")
long threadLocalRandomSeed;
@sun.misc.Contended("tlr")
int threadLocalRandomProbe;
@sun.misc.Contended("tlr")
int threadLocalRandomSecondarySeed;
private native void setPriority0(int newPriority);
private native void stop0(Object o);
private native void suspend0();
private native void resume0();
private native void interrupt0();
private native void setNativeName(String name);
}