怎么去推廣一個網(wǎng)站網(wǎng)頁優(yōu)化方案
目錄
1、等待一個線程:join
1.1 join()
1.2 join(long millis)——"超時時間"
?1.3 join(long millis,int nanos)
2、獲取當(dāng)前線程的引用:currentThread
3、休眠當(dāng)前進程:sleep
3.1 實際休眠時間
3.2 sleep的特殊寫法——sleep(0)
4、線程狀態(tài)
4.1 NEW
4.2?TERMINATED
?4.3 RUNNABLE
4.4?TIMED_WAITING?
4.5?WAITING
1、等待一個線程:join
1.1 join()
在并發(fā)中,我們通常用這樣一個需求,一個線程執(zhí)行完后,另一個線程才能終止,也就是需要控制兩個線程結(jié)束的先后順序。
我們可以通過上篇博客所提到的sleep來設(shè)置線程的休眠時間,從而控制線程的結(jié)束的先后順序,但是這樣的做法是不科學(xué)的。比如,我們需要在t線程結(jié)束后,讓main線程緊跟著結(jié)束,此時sleep就顯得不靠譜了~~
我們就可以通過:
- 在main線程中調(diào)用t.join()方法,來讓main線程等待 t 線程結(jié)束后,main再結(jié)束。
- 當(dāng)代碼執(zhí)行到t.join時,main線程就會發(fā)生"阻塞等待",等待t線程結(jié)束后,join再繼續(xù)執(zhí)行。
join方法也會拋出InterruptedException異常。?
注意:在哪個線程中調(diào)用join,就是哪個線程在"阻塞等待"。
1.2 join(long millis)——"超時時間"
其實上文的join是不科學(xué)的"等待",其實就是不見不散的“死等”,要是另t線程一直沒有結(jié)束,main線程就會一直等待下去。
join還提供了另外一個版本,帶參數(shù)的join(long millis),帶有“超時時間”的等待,“超時時間”即最大的等待時間,當(dāng)?shù)却臅r間超過設(shè)定的“超時時間”后,main就不會繼續(xù)等待下去了,繼續(xù)執(zhí)行join下面的代碼。
例如:在main線程中調(diào)用t.join(3000):
- 當(dāng)main等待的時間超過3秒后,t線程還沒有結(jié)束,main就不會繼續(xù)等待,繼續(xù)行join下面的代碼。
- 當(dāng)main等待的時間還沒有超過3秒時,即在3秒之內(nèi)t已經(jīng)執(zhí)行完了(t提前結(jié)束),此時main也不會再等待了,也會繼續(xù)行join下面的代碼。
帶有超時時間的等待,才是更科學(xué)的等待(當(dāng)電腦或者手機程序卡死的時候,就會彈出等待時間的窗口)。尤其是在和網(wǎng)絡(luò)通信相關(guān)的領(lǐng)域都是需要設(shè)置"超時時間"。
public class Demo10 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {Thread.currentThread();for(int i = 0; i < 3000; i++) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}System.out.println("t 線程終止");});t.start();// main 等待 t//t.join();//main 最多等待 t 3秒//t.join(3000);t.join(3000,500);System.out.println("main 終止");}
}
?1.3 join(long millis,int nanos)
join(long millis,int nanos),nanos即納秒,即"超時時間"精確到納秒級別,是更為精確的等待。對于我們開發(fā)來說,幾乎不會使用。
1s = 1000ms(毫秒),1ms = 1000us(微秒),1us = 1000ns(納秒)
在計算機中,很難做到ns級別的精確測量,即使線程的調(diào)度也是ms級別的開銷。
但是也并非做不到,"實時操作系統(tǒng)"就可以做到更為精確的時間計算,我們平常接觸到的Windows、Linux、Mac、Android系統(tǒng)都不是實時操作系統(tǒng),這類操作系統(tǒng)常用于航天、軍事、工業(yè)領(lǐng)域。實時操作系統(tǒng),其實時性非常高,但是也是在削弱很多功能下達到的,俗話說得好,魚和熊掌不可兼得~~
2、獲取當(dāng)前線程的引用:currentThread
這個方法我們已經(jīng)很熟悉了,上篇博客已經(jīng)為大家進行了講解。
我們只需要記住一點:在哪個線程中調(diào)用,獲取的就是哪個線程的引用(類似于this)。
3、休眠當(dāng)前進程:sleep
3.1 實際休眠時間
這個方法我們也是很熟悉的了。
但是要額外注意一點:實際的休眠時間,往往是要大于我們所設(shè)置的休眠時間的。
使用sleep方法讓線程休眠時,實際是讓當(dāng)前線程讓出CPU資源,當(dāng)休眠時間一到,只能說明當(dāng)前線程是允許被操作系統(tǒng)調(diào)度到CPU上執(zhí)行了,而并不是說明是立即被執(zhí)行。
也就是說還會有一些線程被調(diào)度的時間的開銷,一般是ms級別的開銷。
3.2 sleep的特殊寫法——sleep(0)
sleep(0)是使用sleep的一種特殊寫法。意味著讓當(dāng)前線程立即放棄CPU資源,讓給其他線程,再等待操作系統(tǒng)重新調(diào)度。
當(dāng)一個模塊CPU占有率比較高,影響到其他模塊正常執(zhí)行時,就可以通過這種方式來緩解資源緊張。
?到目前為止,基于對Thread類的學(xué)習(xí),我們已經(jīng)掌握了:
- 創(chuàng)建線程
- 關(guān)鍵屬性
- 終止線程
- 線程等待
- 獲取線程引用
- 線程休眠
接下來,我們再談線程狀態(tài)~?
4、線程狀態(tài)
我們知道 進程 分為以下兩種狀態(tài):
- 就緒
- 阻塞
但是這兩種狀態(tài)都是站在操作系統(tǒng)的視角所定義的,在Java線程中,Java也是對操作系統(tǒng)線程進行了封裝,對于線程狀態(tài)也是重新進行表示。
- NEW: 安排了工作, 還未開始行動
- TERMINATED: 工作完成了
- RUNNABLE: 可工作的。又可以分成正在工作中和即將開始工作
- TIMED_WAITING: 這幾個都表示排隊等著其他事情
- WAITING: 這幾個都表示排隊等著其他事情
- BLOCKED: 這幾個都表示排隊等著其他事情
4.1 NEW
NEW狀態(tài)是指:僅僅new好了Thread對象,但是還沒有創(chuàng)建線程(還沒有start)。
public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {System.out.println("hello t");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});// NEW 狀態(tài)System.out.println(t.getState());}
4.2?TERMINATED
TERMINATED狀態(tài)是指:線程已經(jīng)結(jié)束,但是Thread對象依舊存活。即:線程執(zhí)行完畢。
public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {System.out.println("hello t");});t.start();Thread.sleep(1000);// 此時 t 線程已結(jié)束// TERMINATEDSystem.out.println(t.getState());}
?4.3 RUNNABLE
?RUNNABLE狀態(tài)其實就是就緒狀態(tài),分為以下兩種:
- 線程正在CPU上執(zhí)行
- 線程隨時可以去CPU上執(zhí)行
RUNNABLE是處于NEW和TERMINATED之間的狀態(tài)。?
public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {}});t.start();// t 線程正在執(zhí)行// RUNNABLESystem.out.println(t.getState());}
4.4?TIMED_WAITING?
TIMED_WAITING狀態(tài)是一種阻塞狀態(tài)(不參與CPU調(diào)度,不繼續(xù)執(zhí)行了),但是是有指定時間的阻塞,阻塞的時間有上限。
當(dāng)線程處于以下狀態(tài)時,就為TIMED_WAITING狀態(tài)。
- sleep指定時間內(nèi)休眠時
- 處于使用帶"超時時間"的阻塞等待時
線程sleep前為RUNNABLE狀態(tài),sleep時為TERMINATED狀態(tài),sleep后又回到RUNNABLE狀態(tài)。
public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {while (true) {try {Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t.start();// TIMED_WAITINGThread.sleep(1000);System.out.println(t.getState());}
4.5?WAITING
WAITING也是一種阻塞狀態(tài),只不過是死等,即沒有"超時時間"的阻塞等待。
public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {while (true){}});t.start();// 沒有超時時間的阻塞等待t.join();// 此時main線程就處于 WAITING狀態(tài)}
END