線程Sleep方法介紹
sleep是一個(gè)靜態(tài)方法,有兩個(gè)重載參數(shù),一個(gè)需要轉(zhuǎn)入毫秒數(shù),另一個(gè)需要傳入毫秒和納秒數(shù)。
public static void sleep(long millis) throws InterruptedException;
public static void sleep(long millis,int nanos) throws InterruptedException;
sleep方法會(huì)使當(dāng)前線程進(jìn)入指定方法的休眠,暫停執(zhí)行,其中有一個(gè)很重要的屬性,那就是不會(huì)放棄monitor鎖 ,每個(gè)線程的休眠互不影響。
使用TimeUnit代替Thread.sleep
TimeUnit.Hour.sleep(long millis)
TimeUnit.SECONDS.sleep(long millis)
TimeUnit.MINUTES.sleep(long millis)
顯然TimeUnit比sleep清楚很多。
yield方法
yield方法屬于一種啟發(fā)式的方法,豈會(huì)提醒調(diào)度器我愿意放棄當(dāng)前CPU資源,如果CPU資源不緊張,則會(huì)忽略這種題型。
調(diào)用yield方法會(huì)使當(dāng)前線程RUNNING狀態(tài)切換到RUNNABLE狀態(tài),
yield和sleep方法的區(qū)別
- sleep會(huì)導(dǎo)致當(dāng)前線程暫停到指定的時(shí)間,沒有CPU時(shí)間片的消耗。
- yield只是對(duì)CPU調(diào)度器的一個(gè)提示,如果CPU忽略掉這個(gè)提示,他會(huì)導(dǎo)致線程上下文切換。
- 線程sleep會(huì)導(dǎo)致短暫block,會(huì)再給定時(shí)間內(nèi)釋放CPU資源。
- yield會(huì)使RUNNING 狀態(tài)進(jìn)入RUNNABLE狀態(tài)(如果CPU沒有忽略掉這個(gè)提示的話)
- sleep幾乎百分之百的完成了給定時(shí)間的睡眠,而yield則不一定能擔(dān)保
- 一個(gè)線程sleep另個(gè)線程interrupt會(huì)捕獲中斷信號(hào),而yield不能。
線程的優(yōu)先級(jí)
public final void setPriority(int priority) 為線程設(shè)定優(yōu)先級(jí)
public final int getPriority()獲取線程的優(yōu)先級(jí)
如果指定的線程優(yōu)先級(jí)大于ThreadGroup的優(yōu)先級(jí),那么指定線程的優(yōu)先級(jí)則失效,取而代之的是ThreadGroup的優(yōu)先級(jí)。
獲取線程的ID
public long getId();//獲取線程的ID
線程的Id在整個(gè)JVM是惟一的
獲取當(dāng)前線程
public static Thread currentThread();用于返回當(dāng)前執(zhí)行線程的引用,
設(shè)置線程上下文類加載器
public ClassLoader getContextClassLoader();獲取線程的上下文加載器,簡(jiǎn)單來說這個(gè)線程是由那個(gè)類加載的,如果沒有修改,那么則與父線程保持一致.
public void setContextClassLoader(ClassLoader cl)設(shè)置該線程的類加載,這個(gè)方法可以打破父委托機(jī)制。
線程的interrupt
public void interrupt();
public static boolean interruped();
public boolean isInterrupted();
1.interrupt
當(dāng)前Thread調(diào)用以下方法會(huì)進(jìn)入阻塞狀態(tài),而調(diào)用interrupt方法會(huì)打斷阻塞,
object的wait方法
Thread的Sleep方法
Thread的Join方法
Selector的wakeup方法
調(diào)用上述方法 都會(huì)使得當(dāng)前線程進(jìn)入阻塞狀態(tài),若另外一個(gè)線程調(diào)用被阻塞線程的interrupt方法,則會(huì)打斷這種阻塞,打斷一個(gè)線程的阻塞,并不意味著當(dāng)前線程的生命周期結(jié)束,僅僅是打斷了當(dāng)前的阻塞狀態(tài)。
一個(gè)線程在阻塞的情況下被打斷,則會(huì)跑出interruptedException的異常,
Thread thread = new Thread(){
try{
TimeUnit.MINUTES.Sleep(2);
}catch(interruptedException e){
System.out.println("i 'am be interrupted");
}
}
thread.start();
TimeUnit.MIllISECONDS.Sleep(2);
thread.interrupt();
上述線程 啟動(dòng)的時(shí)候 企圖休眠2分鐘 但是在2毫秒之后,被主線程調(diào)用interrupt打斷了。在線程內(nèi)部存在這命名為interrupt flag 的標(biāo)識(shí),如果一個(gè)線程被interrupt,那么它的flag將被設(shè)置。如果一個(gè)線程在調(diào)用可中斷方法時(shí) 被阻塞,調(diào)用Interrupt 被打斷,那么他的flag將被擦除。
2.isInterrupted
isInterrupted是Thread成員的一個(gè)方法,它判斷當(dāng)前線程是否被打斷,
3.interrupted
interrupted 是一個(gè)靜態(tài)方法,調(diào)用該方法,會(huì)直接擦除掉線程的interrupt標(biāo)識(shí),如果當(dāng)前線程被打斷了,那么第一次調(diào)用interrupt返回true,并且立即擦除了interupt標(biāo)識(shí),第二次以后的調(diào)用永遠(yuǎn)都返回false,
public boolean isInterrupted() {
return isInterrupted(false);
}
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
其實(shí)不難發(fā)現(xiàn),isInterrupted和interrupted 會(huì)調(diào)用同一個(gè)方法,區(qū)別在于是否擦除interrupt標(biāo)識(shí),
線程join
Thread的join方法是一個(gè)非常重要的方法,與sleep一樣,它也是一個(gè)可中斷的方法。
public final void join() throws InteruptedException
public final synchronized void join(long mills,int nanos);
public final synchronized void join (long mills) throws InteruptedException;
線程join的基本用法
join線程A,線程B會(huì)進(jìn)入等待,知道線程A結(jié)束聲明周期,或者到達(dá)給定的時(shí)間,那么再次期間B線程是處于BlOCKED的,而不是線程A.
線程的Join方法會(huì)使當(dāng)前永遠(yuǎn)等待下去,知道期間被另外的線程中斷,或者線程join的線程執(zhí)行之后,當(dāng)然你也可以使用Join的重載方法,指定毫秒數(shù),在指定的時(shí)間到達(dá)之后,當(dāng)前線程也會(huì)阻塞。
如何關(guān)閉一個(gè)線程
1.正常關(guān)閉
線程正常結(jié)束生命周期,完成了自己的使命之后,就會(huì)正常的退出。
2.捕獲中斷信號(hào)線程關(guān)閉
Thread thread = new Thread(){
run(){
System.out.println("i will start work");
while(!isInterupted()){
//working
}
}
}
thread.start();
TimeUnit.MINUTES.Sleep(1);
thread.interrupt();
刪除代碼是通過檢查線程Interrupt的標(biāo)識(shí)來決定是否退出的,如果在線程中執(zhí)行某個(gè)可中斷的方法,則可以通過捕獲中斷信號(hào)的方式來退出。
3.使用volatile開關(guān)
由于線程的interupt標(biāo)識(shí)很有可能被擦除,或者邏輯單元中不會(huì)調(diào)用任何可中斷的方法,所以使用volatile修飾開關(guān)flag關(guān)閉線程也是一種方法。
static class MyTask extends Thread{
private volatile boolean closed = false;
void run(){
while(!false && !isInterrupted()){
//working
}
}
}
進(jìn)程假死
所謂假死就是進(jìn)程雖然存在,但是沒有日志輸出,程序不進(jìn)行任何的工作,看起來就想死了一樣,但是事實(shí)上 他并沒有死,絕大部分的原因是因?yàn)槟硞€(gè)線程阻塞了,或者線程出現(xiàn)了死鎖的情況??山柚鷍ava jdk 的bin目錄下的java visual等工具。