<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          10 張圖聊聊線程的生命周期和常用 APIs

          共 2429字,需瀏覽 5分鐘

           ·

          2020-09-11 03:43

          今天我們來(lái)說(shuō)一下線程的生命周期和常用 APIs:我們需要非常清楚的知道線程的各種狀態(tài),比如排查程序運(yùn)行慢的原因時(shí),就需要看下是不是哪里被阻塞了;另外它也是面試時(shí)非常喜歡問的,如果基礎(chǔ)內(nèi)容都答不好,恐怕直接就掛了。

          本文分為兩大部分,

          1. 線程的 6 大狀態(tài);
          2. 多線程常用的 APIs:
            1. join()
            2. wait()
            3. notify()
            4. yield()
            5. sleep()
            6. currentThread()
            7. getName()
            8. getId()
            9. getPriority()
            10. setPriority()
            11. stop()

          線程狀態(tài)

          關(guān)于線程的狀態(tài),網(wǎng)上各種說(shuō)法都有,比較流行的是 5 種或者 6 種。關(guān)于 5 種狀態(tài)的那個(gè)版本我沒有找到理論依據(jù),如果有小伙伴清楚的也歡迎留言指出。

          我這里所寫的是根據(jù) java.lang.Thread 的源碼,線程有以下 6 大狀態(tài):

          public?enum?State?{
          ??NEW,
          ??RUNNABLE,
          ??BLOCKED,
          ??WAITTING,
          ??TIMED_WAITTING,
          ??TERMINATED;
          }

          先上圖,我們?cè)僖来蝸?lái)看。

          1. New

          A thread that has not yet started is in this state.

          就是指線程剛創(chuàng)建,還沒啟動(dòng)的時(shí)候,比如剛 new 了一個(gè) thread。

          MyThread?myThread?=?new?MyThread();

          2. Runnable

          A thread is executing in the Java virtual machine but it may be waiting for other resources from the operating system such as processor.

          那么接下來(lái),自然就是要啟動(dòng)線程了,也就是調(diào)用 threadstart() 方法。

          myThread.start();

          啟動(dòng)之后,線程就進(jìn)入了 Runnable 狀態(tài)。

          此時(shí)所有的線程都會(huì)添加到一個(gè)等待隊(duì)列里,等待“CPU 調(diào)度”。

          如果搶占到 CPU 的資源,那就執(zhí)行;如果沒搶到,就等著唄,等當(dāng)前正在執(zhí)行的線程完成它能執(zhí)行的時(shí)間片之后,再次搶占。

          要注意這里在等待的一般是系統(tǒng)資源,而不是鎖或者其他阻塞。

          3. Blocked

          Thread state for a thread blocked waiting for a monitor lock.
          A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method or reenter a synchronized block/method after calling wait() Object.

          這里給出了非常明確的 use case,就是被鎖在外面的才叫阻塞。所以這里必須要有至少 2 個(gè)線程。

          4. Waiting

          A thread in the waiting state is waiting for another thread to perform a particular action.

          那具體有哪些原因呢?

          A thread is in the waiting state due to calling one of the following methods:

          • Object.wait with no timeout
          • Thread.join with no timeout
          • LockSupport.park

          所以說(shuō),當(dāng)調(diào)用了

          • wait(),
          • join()
          • park()
            方法之后,線程進(jìn)入等待狀態(tài)。

          這里的等待狀態(tài)是沒有時(shí)間限制的,可以無(wú)限的等下去... 所以需要有人來(lái)喚醒

          1. 如果是通過 wait() 進(jìn)入等待狀態(tài)的,需要有 notify() 或者 notifyAll() 方法來(lái)喚醒;
          2. 如果是通過 join() 進(jìn)入等待狀態(tài)的,需要等待目標(biāo)線程運(yùn)行結(jié)束。

          比如在生產(chǎn)者消費(fèi)者模型里,當(dāng)沒有商品的時(shí)候,消費(fèi)者就需要等待,等待生產(chǎn)者生產(chǎn)好了商品發(fā) notify()。下一篇文章我們會(huì)細(xì)講。

          5. Timed_waiting

          導(dǎo)致這個(gè)狀態(tài)的原因如下:

          • Thread.sleep
          • Object.wait with timeout
          • Thread.join with timeout
          • LockSupport.parkNanos
          • LockSupport.parkUntil

          其實(shí)就是在上一種狀態(tài)的基礎(chǔ)上,給了具體的時(shí)間限制

          那么當(dāng)時(shí)間結(jié)束后,線程就解放了。

          6. Terminated

          A thread that has exited is in this state.

          這里有 3 種情況會(huì)終止線程:

          • 執(zhí)行完所有代碼,正常結(jié)束;
          • 強(qiáng)制被結(jié)束,比如調(diào)用了 stop() 方法,現(xiàn)在已經(jīng)被棄用;
          • 拋出了未捕獲的異常。

          線程一旦死亡就不能復(fù)生。

          如果在一個(gè)死去的線程上調(diào)用 start() 方法,那么程序會(huì)拋出 java.lang.IllegalThreadStateException。

          接下來(lái)我們說(shuō)說(shuō)多線程中常用的 11 個(gè) APIs。

          APIs

          1. join()

          join() 方法會(huì)強(qiáng)制讓該線程執(zhí)行,并且一直會(huì)讓它執(zhí)行完。

          比如上一篇文章的例子是兩個(gè)線程交替執(zhí)行的,那么我們這里該下,改成調(diào)用小齊線程.join(),那么效果就是先輸出 小齊666。

          public?class?MyRunnable?implements?Runnable?{
          ????@Override
          ????public?void?run()?{
          ????????for(int?i?=?0;?i?100;?i++)?{
          ????????????System.out.println("小齊666:"?+?i);
          ????????}
          ????}

          ????public?static?void?main(String[]?args)?throws?InterruptedException?{
          ????????Thread?t?=?new?Thread(new?MyRunnable());
          ????????t.start();
          ????????t.join();

          ????????for(int?i?=?0;?i?100;?i++)?{
          ????????????System.out.println("主線程"?+?i?+?":齊姐666");
          ????????}
          ????}
          }

          所以 join() 能夠保證某個(gè)線程優(yōu)先執(zhí)行,而且會(huì)一直讓它執(zhí)行完,再回歸到公平競(jìng)爭(zhēng)狀態(tài)。

          join() 方法其實(shí)是用 wait() 來(lái)實(shí)現(xiàn)的,我們來(lái)看下這個(gè)方法。

          2. wait() and notify()

          wait() 其實(shí)并不是 Thread 類的方法,而是 Object 里面的方法。

          該方法就是讓當(dāng)前對(duì)象等待,直到另一個(gè)對(duì)象調(diào)用 notify() 或者 notifyAll()

          當(dāng)然了,我們也可以設(shè)定一個(gè)等待時(shí)長(zhǎng),到時(shí)間之后對(duì)象將會(huì)自動(dòng)蘇醒。

          4. yield()

          yield 本身的中文意思是屈服,用在這里倒也合適。

          yield() 表示當(dāng)前線程主動(dòng)讓出 CPU 資源一下,然后我們?cè)僖黄鹑尅?/p>

          注意這里讓一下真的只是一下,從“執(zhí)行中”回到“等待 CPU 分配資源”,然后所有線程再一起搶占資源。

          5. sleep()

          顧名思義,這個(gè)方法就是讓當(dāng)前線程睡一會(huì),比如說(shuō),

          myThread.sleep(1000);?//?睡眠?1?秒鐘

          它會(huì)拋出一個(gè) InterruptedException 異常,所以還要 try catch 一下。

          6. currentThread()

          Returns a reference to the currently executing thread object.

          該方法是獲取當(dāng)前線程對(duì)象。

          注意它是一個(gè) static 方法,所以直接通過 Thread 類調(diào)用。

          比如打印當(dāng)前線程

          System.out.println(Thread.currentThread());

          前文的例子中,它會(huì)輸出:

          Thread[Thread-0,5,main]
          Thread[main,5,main]

          沒錯(cuò),它的返回值也是 Thread 類型。

          7. getName()

          該方法可以獲取當(dāng)前線程名稱。

          這個(gè)名稱可以自己設(shè)置,比如:

          Thread?t?=?new?Thread(new?MyRunnable(),?"壹齊學(xué)");

          8. getId()

          該方法是獲取線程的 Id.

          9. getPriority()

          線程也有優(yōu)先級(jí)的哦~

          雖然優(yōu)先級(jí)高的線程并不能百分百保證一定會(huì)先執(zhí)行,但它是有更大的概率被先執(zhí)行的。

          優(yōu)先級(jí)的范圍是 1-10,我們來(lái)看源碼:

          ????/**
          ?????*?The?minimum?priority?that?a?thread?can?have.
          ?????*/

          ????public?final?static?int?MIN_PRIORITY?=?1;

          ???/**
          ?????*?The?default?priority?that?is?assigned?to?a?thread.
          ?????*/

          ????public?final?static?int?NORM_PRIORITY?=?5;

          ????/**
          ?????*?The?maximum?priority?that?a?thread?can?have.
          ?????*/

          ????public?final?static?int?MAX_PRIORITY?=?10;

          如果不在這個(gè)范圍,JDK 拋出 IllegalArgumentException() 的異常。

          10. setPriority()

          當(dāng)然啦,我們也是可以自己設(shè)置某個(gè)線程的優(yōu)先級(jí)的。

          設(shè)置的優(yōu)先級(jí)也需要在規(guī)定的 1-10 的范圍內(nèi)哦,如果不在這個(gè)范圍也會(huì)拋異常。

          11. stop()

          最后我們來(lái)說(shuō)下 stop() 方法,也是前文提到過的強(qiáng)制停止線程的一種方式,但現(xiàn)在已被棄用,因?yàn)闀?huì)引起一些線程安全方面的問題。

          好了,以上就是有關(guān)線程狀態(tài)和常用 API 的介紹了。相信大家看完之后對(duì)線程的整個(gè)流程應(yīng)該有了清晰的認(rèn)識(shí),其實(shí)里面還有很多細(xì)節(jié)我沒有展開,畢竟這是多線程的第 2 講,更深入的內(nèi)容我們慢慢來(lái)。

          如果你喜歡這篇文章,記得給我點(diǎn)贊留言哦~你們的支持和認(rèn)可,就是我創(chuàng)作的最大動(dòng)力,我們下篇文章見!

          瀏覽 24
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  麻豆蜜桃成人免费视频 | 成人性生活免费视频 | 正在播放熟女 | 天天插天天透天天抽 | 一区二区三区四区五区六区七区八区九区 |