線程狀態(tài)

線程狀態(tài)

線程狀態(tài)
  1. 新建狀態(tài)

    new出一個(gè)線程伞芹,線程還沒有開始運(yùn)行忘苛,當(dāng)線程處于新建狀態(tài)時(shí)蝉娜,程序還沒有運(yùn)行線程中的代碼。

  2. 就緒狀態(tài)
    當(dāng)線程對象調(diào)用start()方法即啟動(dòng)了線程扎唾,start()方法創(chuàng)建線程運(yùn)行的系統(tǒng)資源召川,并調(diào)度線程運(yùn)行run()方法。當(dāng)start()方法返回后胸遇,線程就處于就緒狀態(tài)荧呐。

    處于就緒狀態(tài)的線程并不一定立即運(yùn)行run()方法,線程還必須同其他線程競爭CPU時(shí)間纸镊,只有獲得CPU時(shí)間才可以運(yùn)行線程倍阐。對處于就緒狀態(tài)的線程是由Java運(yùn)行時(shí)系統(tǒng)的線程調(diào)度程序(thread scheduler)來調(diào)度的。

  3. 運(yùn)行狀態(tài)

    當(dāng)線程獲得CPU時(shí)間后逗威,它才進(jìn)入運(yùn)行狀態(tài)峰搪,真正開始執(zhí)行run()方法。

  4. 阻塞狀態(tài)

    當(dāng)一個(gè)線程試圖獲取一個(gè)內(nèi)部的對象鎖(非java.util.concurrent庫中的鎖)凯旭,而該鎖被其他線程持有概耻,則該線程進(jìn)入阻塞狀態(tài)。

  5. 等待狀態(tài)
    處于等待狀態(tài)的線程正在等待另一個(gè)線程執(zhí)行特定操作罐呼,例如Object.wait()等待一個(gè)線程notify鞠柄,Thread.join()等待另一個(gè)線程執(zhí)行結(jié)束。

  6. 死亡狀態(tài)

    有兩個(gè)原因會(huì)導(dǎo)致線程死亡:

    (1)run方法正常退出而自然死亡嫉柴,

    (2)一個(gè)未捕獲的異常終止了run方法而使線程猝死厌杜。

線程調(diào)度

線程休眠

線程睡眠是線程主動(dòng)讓出CPU讓其他線程執(zhí)行,線程從運(yùn)行狀態(tài)切換為阻塞狀態(tài)差凹,線程休眠是其他線程執(zhí)行的有效方法期奔,但是休眠時(shí)間到休眠線程未必執(zhí)行侧馅,它的執(zhí)行依靠CPU的調(diào)度危尿。但是線程在休眠的時(shí)候仍然占有鎖,而且sleep()是靜態(tài)方法馁痴,只能控制當(dāng)前正在運(yùn)行的線程谊娇。

/**
 *  睡眠
 *  一個(gè)計(jì)數(shù)器,計(jì)數(shù)到 100,在每個(gè)數(shù)字之間暫停 1 秒,每隔 10 個(gè)數(shù)字輸出一個(gè)字符串
 */

public class ThreadSleep {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            public void run() {
                for(int i = 0; i < 100; i++){
                    if((i) % 10 ==0 ){
                        System.out.println("************");
                    }
                    try {
                        Thread.sleep(1);
                        System.out.println("i的值是:" + i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

線程讓步

運(yùn)行狀態(tài)的線程讓出CPU資源,但是然給誰不知道罗晕,僅僅是讓出济欢,也有可能是自己,線程從運(yùn)行狀態(tài)切換為阻塞狀態(tài)小渊。

public class ThreadYield {
    public static void main(String[] args) {
        Thread t1 = new MyThread1();
        Thread t2 = new Thread(new MyRunnable());
        
        t2.start();
        t1.start();
    }
    static class MyThread1 extends Thread {
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println("線程1第" + i + "次執(zhí)行法褥!");
            }
        }
    }

    static class MyRunnable implements Runnable {
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println("線程2第" + i + "次執(zhí)行!");
                Thread.yield();
            }
        }
    }

}
//執(zhí)行結(jié)果(可以看出線程線程1執(zhí)行完后線程1開始執(zhí)行)
線程2第0次執(zhí)行酬屉!
線程1第0次執(zhí)行半等!
線程1第1次執(zhí)行揍愁!
線程1第2次執(zhí)行!
線程1第3次執(zhí)行杀饵!
線程1第4次執(zhí)行莽囤!
線程1第5次執(zhí)行!
線程1第6次執(zhí)行切距!
線程1第7次執(zhí)行朽缎!
線程1第8次執(zhí)行!
線程1第9次執(zhí)行谜悟!
線程2第1次執(zhí)行话肖!
線程2第2次執(zhí)行!
線程2第3次執(zhí)行赌躺!
線程2第4次執(zhí)行狼牺!
線程2第5次執(zhí)行!
線程2第6次執(zhí)行礼患!
線程2第7次執(zhí)行是钥!
線程2第8次執(zhí)行!
線程2第9次執(zhí)行缅叠!

線程合并

現(xiàn)在有線程A悄泥、線程B,線程合并是將線程A肤粱、B合二為一弹囚,線程A先執(zhí)行,然后調(diào)用join方法领曼,則線程B開始執(zhí)行鸥鹉,等B執(zhí)行完成后A再接著上次繼續(xù)執(zhí)行。應(yīng)用場景是當(dāng)一個(gè)線程必須等待另一個(gè)線程執(zhí)行完畢才能執(zhí)行時(shí)可以使用join方法庶骄。

public class ThreadJoin extends Thread {
    public static void main(String[] args) {
        Thread t1 = new MyThread2();
        t1.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("主線程第" + i + "次執(zhí)行!");
            if (i > 2) try {
            //t1 線程合并到主線程中,主線程停止執(zhí)行過程,轉(zhuǎn)而執(zhí)行 t1 線程, 直到 t1 執(zhí)行完畢后繼續(xù)毁渗。
                t1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


class MyThread2 extends Thread {
    public void run() {
        for (int i = 0; i < 4; i++) {
            System.out.println("線程 1 第" + i + "次執(zhí)行!");
        }
    }
}
//執(zhí)行結(jié)果
主線程第0次執(zhí)行!
主線程第1次執(zhí)行!
主線程第2次執(zhí)行!
主線程第3次執(zhí)行!
線程 1 第0次執(zhí)行!
線程 1 第1次執(zhí)行!
線程 1 第2次執(zhí)行!
線程 1 第3次執(zhí)行!
主線程第4次執(zhí)行!
主線程第5次執(zhí)行!
主線程第6次執(zhí)行!
主線程第7次執(zhí)行!
主線程第8次執(zhí)行!
主線程第9次執(zhí)行!

線程守候

守護(hù)線程在沒有用戶線程可服務(wù)時(shí)自動(dòng)離開,在Java虛擬機(jī)中當(dāng)正在運(yùn)行的線程都是守護(hù)線程時(shí)单刁,Java虛擬機(jī)退出灸异。調(diào)用線程對象的方法setDaemon(true),則可以將其設(shè)置為守護(hù)線程羔飞,該方法必須在線程調(diào)用前執(zhí)行肺樟。

public class ThreadDaemon {
    public static void main(String[] args) {
        Thread t1 = new MyCommon();
        Thread t2 = new MyDaemon();
        t2.setDaemon(true);
        t1.start();
        t2.start();

    }
}

class MyCommon extends Thread {
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("線程MyCommon第" + i + "次執(zhí)行!");
            try {
                Thread.sleep(7);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


class MyDaemon extends Thread {
    public void run() {
        for (int i = 0; i < 400; i++) {
            System.out.println("線程  MyDaemon  第" + i + "次執(zhí)行!");
            try {
                Thread.sleep(7);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}
//執(zhí)行結(jié)果(MyDaemon線程還沒有執(zhí)行完成便退出)
線程MyCommon第0次執(zhí)行!
線程  MyDaemon  第0次執(zhí)行!
線程  MyDaemon  第1次執(zhí)行!
線程MyCommon第1次執(zhí)行!
線程MyCommon第2次執(zhí)行!
線程  MyDaemon  第2次執(zhí)行!
線程MyCommon第3次執(zhí)行!
線程  MyDaemon  第3次執(zhí)行!
線程MyCommon第4次執(zhí)行!
線程  MyDaemon  第4次執(zhí)行!
線程  MyDaemon  第5次執(zhí)行!

線程優(yōu)先級

線程的有限執(zhí)行順序,優(yōu)先級1~10逻淌,數(shù)值越大優(yōu)先級越高么伯。在一個(gè)線程中開啟另外一個(gè)新線程,則新開線程稱為該線程的子線程卡儒,子線程初始優(yōu)先級與父線程相同田柔。

注意:線程的優(yōu)先級仍然無法保障線程的執(zhí)行次序誓篱。只不過,優(yōu)先級高的線程獲取CPU資源的概率較大凯楔,優(yōu)先級低的并非沒機(jī)會(huì)執(zhí)行窜骄。

public class ThreadPriority {
    public static void main(String[] args) {
        Thread threadA = new Thread(new ThreadA());
        Thread threadB = new Thread(new ThreadB());
        threadA.setPriority(10);
        threadB.setPriority(1);

        threadB.start();
        threadA.start();
    }

}

class ThreadA extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("    A線程第" + i + "次執(zhí)行");
        }
    }
}

class ThreadB extends Thread {
    @Override
    public void run() {
        for (int j = 0; j < 10; j++) {
            System.out.println("B線程第" + j + "次執(zhí)行");
        }
    }
}
//執(zhí)行結(jié)果
B線程第0次執(zhí)行
B線程第1次執(zhí)行
    A線程第0次執(zhí)行
B線程第2次執(zhí)行
    A線程第1次執(zhí)行
    A線程第2次執(zhí)行
B線程第3次執(zhí)行
B線程第4次執(zhí)行
B線程第5次執(zhí)行
B線程第6次執(zhí)行
B線程第7次執(zhí)行
B線程第8次執(zhí)行
B線程第9次執(zhí)行
    A線程第3次執(zhí)行

問題

  1. 為什么synchronized等到獲取鎖是阻塞,而ReentrantLock是阻塞摆屯。

代碼驗(yàn)證:

public class StatusDemo {
    static Object lock = new Object();

    public static void read() {
        synchronized (lock) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("讀數(shù)據(jù)");
        }
    }

    public static void write() {
        synchronized (lock) {
            System.out.println("寫數(shù)據(jù)");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                StatusDemo.read();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                StatusDemo.write();
            }
        }).start();

    }
}
public class StatusDemo {
      static  ReentrantLock lock = new ReentrantLock();

    public static void read() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+"讀數(shù)據(jù)");
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void write() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+"寫數(shù)據(jù)");
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                StatusDemo1.read();
            }
        }).start();


        new Thread(new Runnable() {
            @Override
            public void run() {
                StatusDemo1.write();
            }
        }).start();

    }
}

為什么ReentrantLock是阻塞呢邻遏,看ReentrantLock的源碼你會(huì)發(fā)現(xiàn),其實(shí)ReentrantLock是AQS實(shí)現(xiàn)的虐骑,而AQS中使用了park()和unpark().

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末准验,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子廷没,更是在濱河造成了極大的恐慌糊饱,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件颠黎,死亡現(xiàn)場離奇詭異另锋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)狭归,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進(jìn)店門夭坪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人过椎,你說我怎么就攤上這事室梅。” “怎么了疚宇?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵亡鼠,是天一觀的道長。 經(jīng)常有香客問我敷待,道長间涵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任讼撒,我火速辦了婚禮浑厚,結(jié)果婚禮上股耽,老公的妹妹穿的比我還像新娘根盒。我一直安慰自己,他們只是感情好物蝙,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布炎滞。 她就那樣靜靜地躺著,像睡著了一般诬乞。 火紅的嫁衣襯著肌膚如雪册赛。 梳的紋絲不亂的頭發(fā)上钠导,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天,我揣著相機(jī)與錄音森瘪,去河邊找鬼牡属。 笑死,一個(gè)胖子當(dāng)著我的面吹牛扼睬,可吹牛的內(nèi)容都是我干的逮栅。 我是一名探鬼主播,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼窗宇,長吁一口氣:“原來是場噩夢啊……” “哼措伐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起军俊,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤侥加,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后粪躬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體担败,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年镰官,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了氢架。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,912評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡朋魔,死狀恐怖岖研,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情警检,我是刑警寧澤孙援,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站扇雕,受9級特大地震影響拓售,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜镶奉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一础淤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧哨苛,春花似錦鸽凶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至亿蒸,卻和暖如春凑兰,著一層夾襖步出監(jiān)牢的瞬間掌桩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工姑食, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留波岛,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓音半,卻偏偏與公主長得像盆色,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子祟剔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評論 2 361