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