Thread各種state

線程thread的狀態(tài)有六種:
new、terminal、runnable、waiting、timed_waiting、block

它們的關(guān)系圖如下:


代碼測(cè)試:

/**
 * 線程的狀態(tài),有六種:
 * NEW 、新建
 * RUNNABLE 、可運(yùn)行
 * WAITING、等待
 * TIMED_WAITING、限時(shí)等待
 * BLOCKED、阻塞
 * TERMINAL、終止
 *
 * @author Administrator
 */
public class ThreadState {

    public static void main(String[] args) {
        System.out.println("============================測(cè)試 NEW RUNNABLE TERMINAL TIMED_WAITING============================");
        Sub a = new Sub("a");
        SmallTool.printTimeAndThread("新建了一個(gè)線程a,但還沒(méi)start,狀態(tài):" + a.getState());//NEW

        a.start();
        SmallTool.printTimeAndThread("線程a已經(jīng)start,狀態(tài)是:" + a.getState());//RUNNABLE

        SmallTool.printTimeAndThread("待線程" + Thread.currentThread() + "睡20ms,讓cpu給a線程,讓它睡眠5s");
        SmallTool.sleepMillis(20);
        SmallTool.printTimeAndThread("查看a線程的狀態(tài):" + a.getState());//TIMED_WAITING
        SmallTool.sleepMillis(5000);
        SmallTool.printTimeAndThread("睡眠超過(guò)a的5s,查看a的狀態(tài):" + a.getState());//TERMINATED

        //**************************************************************************************************

         System.out.println("============================測(cè)試BLOCK============================");

         Block b = new Block("b");
         Block c = new Block("c");
         b.start();
         SmallTool.printTimeAndThread("b已經(jīng)啟動(dòng),c在20ms后啟動(dòng),讓b拿著synchronize鎖,睡眠5s");
         SmallTool.sleepMillis(20);
         c.start();
         SmallTool.sleepMillis(20);
         SmallTool.printTimeAndThread("待c啟動(dòng)成功之后,查看狀態(tài),b=" + b.getState() + " , c=" + c.getState());//b=TIMED_WAITING , c=BLOCKED
         SmallTool.printTimeAndThread("c正在" + c.getState() + ",嘗試打斷它");
         c.interrupt();
         SmallTool.printTimeAndThread("在c被打斷后,查看打斷標(biāo)志:" + c.isInterrupted() + ",狀態(tài):" + c.getState());//isInterrupted=false, RUNNABLE
         SmallTool.printTimeAndThread("c響應(yīng)中斷后不會(huì)再執(zhí)行run()方法D的睡5s,立馬往下執(zhí)行異常代碼");

         //*******************************************************************************************************
         SmallTool.sleepMillis(5 * 1000);

         Wait d = new Wait("d");
         SmallTool.sleepMillis(20);
         System.out.println("============================測(cè)試WAIT 和 打斷它============================");
         d.start();
         SmallTool.sleepMillis(20);
         SmallTool.printTimeAndThread("d已經(jīng)啟動(dòng)成功,內(nèi)執(zhí)行wait(),查看狀態(tài): " + d.getState()); //WAITING
         SmallTool.sleepMillis(20);
         SmallTool.printTimeAndThread("過(guò)20ms打斷d,會(huì)拋出異常");
         d.interrupt();
    }
    /**
     * 運(yùn)行結(jié)果:
     * ============================測(cè)試 NEW RUNNABLE TERMINAL TIMED_WAITING============================
     1642177805719  |   1   |   main    |   新建了一個(gè)線程a,但還沒(méi)start,狀態(tài):NEW
     1642177805721  |   1   |   main    |   線程a已經(jīng)start,狀態(tài)是:RUNNABLE
     1642177805722  |   1   |   main    |   待線程Thread[main,5,main]睡20ms,讓cpu給a線程,讓它睡眠5s
     1642177805733  |   11  |   a   |   在run()方法中睡眠5s...
     1642177805762  |   1   |   main    |   查看a線程的狀態(tài):TIMED_WAITING
     1642177810800  |   1   |   main    |   睡眠超過(guò)a的5s,查看a的狀態(tài):TERMINATED


     ============================測(cè)試BLOCK============================
     1642177810867  |   1   |   main    |   b已經(jīng)啟動(dòng),c在20ms后啟動(dòng),讓b拿著synchronize鎖,睡眠5s
     1642177810925  |   1   |   main    |   待c啟動(dòng)成功之后,查看狀態(tài),b=TIMED_WAITING , c=BLOCKED
     1642177810925  |   1   |   main    |   c正在BLOCKED,嘗試打斷它
     1642177810925  |   1   |   main    |   在c被打斷后,查看打斷標(biāo)志:true,狀態(tài):BLOCKED
     1642177810925  |   1   |   main    |   c響應(yīng)中斷后不會(huì)再執(zhí)行run()方法D的睡5s,立馬往下執(zhí)行異常代碼
     1642177815886  |   12  |   b   |   完成業(yè)務(wù)了,狀態(tài)是:RUNNABLE
     1642177815886  |   13  |   c   |   在-- block --被打斷并清除中斷標(biāo)志,標(biāo)志:false,狀態(tài)是:RUNNABLE
     1642177815886  |   13  |   c   |   完成業(yè)務(wù)了,狀態(tài)是:RUNNABLE


     ============================測(cè)試WAIT 和 打斷它============================
     1642177815998  |   1   |   main    |   d已經(jīng)啟動(dòng)成功,內(nèi)執(zhí)行wait(),查看狀態(tài): WAITING
     1642177816029  |   1   |   main    |   過(guò)20ms打斷d,會(huì)拋出異常
     1642177816029  |   14  |   d   |   在-- wait --被打斷并清除中斷標(biāo)志,狀態(tài)是:RUNNABLE
     *
     */
}

class Sub extends Thread {

    public Sub(String name) {
        super(name);
    }

    @Override
    public void run() {
        SmallTool.printTimeAndThread("在run()方法中睡眠5s...");
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            SmallTool.printTimeAndThread("在-- sub --被打斷并清除中斷標(biāo)志,狀態(tài)是:" + Thread.currentThread().getState());
        }
    }
}

class Block extends Thread {
    public Block(String name) {
        super(name);
    }

    @Override
    public void run() {
        synchronized (Block.class) {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                SmallTool.printTimeAndThread("在-- block --被打斷并清除中斷標(biāo)志,標(biāo)志:"
                        + Thread.currentThread().isInterrupted() + ",狀態(tài)是:" + Thread.currentThread().getState());
            } finally {
                SmallTool.printTimeAndThread("完成業(yè)務(wù)了,狀態(tài)是:" + Thread.currentThread().getState());
            }
        }
    }
}

class Wait extends Thread {
    public Wait(String name) {
        super(name);
    }

    @Override
    public void run() {
        synchronized (this) {
            try {
                wait();
            } catch (InterruptedException e) {
                SmallTool.printTimeAndThread("在-- wait --被打斷并清除中斷標(biāo)志,狀態(tài)是:" + Thread.currentThread().getState());//WAITING
            }
        }
    }
}

關(guān)于LockSupport的park之后的狀態(tài)

LockSupport的park被調(diào)用之后,線程狀態(tài)是WAITING,可以使用lockSupport的unpark或者使用該線程的interrupt方法來(lái)打斷,它倆都可以使程序繼續(xù)運(yùn)行。

測(cè)試代碼:


/**
 * 測(cè)試lockSupport的狀態(tài)、使用unpark和interrupt之后的狀態(tài)
 *
 * 可以知道lockSupport的park之后,線程是處于waiting狀態(tài)的
 *
 * @author Administrator
 */
public class LockSupportState {

    public static void main(String[] args) {
        System.out.println("============================測(cè)試LockSupport是WAITING,以及unPark============================");
        LockSupportPark e = new LockSupportPark("e");

        e.start();
        SmallTool.sleepMillis(20);
        SmallTool.printTimeAndThread("讓e被park住,查看狀態(tài),e:" + e.getState());
        LockSupport.unpark(e);
        SmallTool.sleepMillis(20);
        SmallTool.printTimeAndThread("之后main線程使用unpark喚醒它,查看狀態(tài),e:" + e.getState());

        SmallTool.sleepMillis(20);
        System.out.println("============================測(cè)試LockSupport是WAITING,以及打斷============================");

        LockSupportPark f = new LockSupportPark("f");
        f.start();
        SmallTool.sleepMillis(20);
        SmallTool.printTimeAndThread("讓f被park住,查看狀態(tài),f:" + f.getState());
        f.interrupt();
        SmallTool.sleepMillis(20);
        SmallTool.printTimeAndThread("之后main線程使用interrupt打斷它,查看狀態(tài),f:" + f.getState());
    }
    /**
     * 運(yùn)行結(jié)果:
     ============================測(cè)試LockSupport是WAITING,以及unPark============================
     1642177729984  |   11  |   e   |   e線程被park之前
     1642177730013  |   1   |   main    |   讓e被park住,查看狀態(tài),e:WAITING
     1642177730013  |   11  |   e   |   e線程被park之后
     1642177730045  |   1   |   main    |   之后main線程使用unpark喚醒它,查看狀態(tài),e:TERMINATED


     ============================測(cè)試LockSupport是WAITING,以及打斷============================
     1642177730077  |   12  |   f   |   f線程被park之前
     1642177730109  |   1   |   main    |   讓f被park住,查看狀態(tài),f:WAITING
     1642177730109  |   12  |   f   |   f線程被park之后
     1642177730141  |   1   |   main    |   之后main線程使用interrupt打斷它,查看狀態(tài),f:TERMINATED

     */
}


class LockSupportPark extends Thread {

    public LockSupportPark(String name) {
        super(name);
    }

    @Override
    public void run() {
        SmallTool.printTimeAndThread(currentThread().getName() + "線程被park之前");
        LockSupport.park(this);
        SmallTool.printTimeAndThread(currentThread().getName() + "線程被park之后");
    }
}

結(jié)論

對(duì)比一開(kāi)始的圖片,以上的測(cè)試結(jié)果基本都是符合的,進(jìn)入BLOCKED的只有synchronize的,其余變成WAITING的,都是lockSupport、wait、join、sleep之類的。

而且,通過(guò)以上實(shí)驗(yàn),NEW和TERMINATED對(duì)于中斷操作幾乎是屏蔽的,RUNNABLE和BLOCKED類似,對(duì)于中斷操作只是設(shè)置中斷標(biāo)志位并沒(méi)有強(qiáng)制終止線程,對(duì)于線程的終止權(quán)利依然在程序手中。WAITING/TIMED_WAITING狀態(tài)下的線程對(duì)于中斷操作是敏感的,他們會(huì)拋出異常并清空中斷標(biāo)志位。

參考:
Java并發(fā)之線程中斷
LockSupport.park的線程狀態(tài)以及如何解除

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 什么是線程 線程(thread)是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位。它被包含在進(jìn)程之中,一個(gè)進(jìn)程中可以并發(fā)多個(gè)線...
    刀哥說(shuō)Java閱讀 544評(píng)論 0 6
  • 2.1 線程狀態(tài)簡(jiǎn)介 在java.lang.Thread.State中能清楚的看到Java中定義了6種狀態(tài): Ne...
    Vander1991閱讀 239評(píng)論 0 0
  • 1 線程簡(jiǎn)介 首先我們要清楚的是,任何程序想要實(shí)現(xiàn)線程都需要內(nèi)核線程的支持,至少要有一個(gè),不然程序無(wú)法執(zhí)行。用戶線...
    JavaM閱讀 604評(píng)論 0 1
  • Thread的六種狀態(tài) NEWThread對(duì)象被創(chuàng)建,也即被初始化后,且未執(zhí)行start()函數(shù)之前的狀態(tài) RUN...
    Doctor_Xu閱讀 400評(píng)論 0 0
  • 線程天天用,看過(guò)其完整源碼的有多少? 線程目錄 構(gòu)造 啟動(dòng) 狀態(tài) 中斷 構(gòu)造 創(chuàng)建一個(gè)線程有幾種方式? Threa...
    sunyelw閱讀 275評(píng)論 0 0

友情鏈接更多精彩內(nèi)容