Java多線程3-Thread簡介

聲明:原創(chuàng)文章迎吵,轉(zhuǎn)載請注明出處汰聋。http://www.reibang.com/p/4f9de47d1c43

一恩伺、線程生命周期

線程的狀態(tài)有NEW鹤树、RUNNABLE铣焊、RUNNING、BLOCKED和TERMINATED五個(gè)狀態(tài)罕伯。如下圖所示:


Thread生命周期
  • NEW:當(dāng)我們new一個(gè)Thread對象后曲伊,在沒有執(zhí)行start方法之前,這僅僅是一個(gè)普通的Java對象》啬迹可以說線程處于NEW狀態(tài)岛蚤。
  • RUNNABLE:當(dāng)執(zhí)行start方法后,JVM會(huì)創(chuàng)建一個(gè)線程并進(jìn)入RUNNABLE狀態(tài)懈糯,等待操作系統(tǒng)的調(diào)度涤妒。
  • RUNNING:當(dāng)操作系統(tǒng)調(diào)度處于RUNNABLE狀態(tài)的線程成功后,此時(shí)該線程處于執(zhí)行狀態(tài)赚哗,并執(zhí)行其邏輯代碼她紫。如果調(diào)用stop方法則進(jìn)入TERMINATED狀態(tài);調(diào)用sleep/wait屿储、獲取鎖資源或進(jìn)行某個(gè)IO阻塞會(huì)進(jìn)入BLOCKED狀態(tài)贿讹;CPU時(shí)間片用完或者調(diào)用yield方法(放棄CPU執(zhí)行),則會(huì)進(jìn)入RUNNABLE狀態(tài)够掠。
  • BLOCKED:阻塞狀態(tài)民褂。
  • TERMINATED:終止?fàn)顟B(tài)。

二疯潭、start()和run()方法的區(qū)別

如下赊堪,我們新建一個(gè)線程,并執(zhí)行start()方法袁勺,使其進(jìn)入RUNNABLE狀態(tài)雹食。然而我們重寫的run()方法卻執(zhí)行了塘安,這是為什么桐愉?

public static void main(String[] args) {
    Thread t1 = new Thread() {
       @Override
        public void run() {
            System.out.println("hello world.");
        }
    };
    t1.start();
}

我們看下start()的源碼:

public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

可以看到怎虫,start()方法的核心為:start0()方法邑商。start0()為native方法磷斧。在線程執(zhí)行時(shí)愉适,start0()會(huì)調(diào)用run()方法啸盏。

結(jié)論1:啟動(dòng)線程什湘,應(yīng)該執(zhí)行start()方法埠通。如果調(diào)用run()方法赎离,有時(shí)會(huì)看到相同的執(zhí)行結(jié)果,但實(shí)際上只是執(zhí)行了Thread對象的一個(gè)普通方法端辱,并沒有多線程運(yùn)行梁剔。

結(jié)論2:從start()的源碼可以看到,如果執(zhí)行兩次start()舞蔽,會(huì)出現(xiàn)IllegalThreadStateException荣病。

結(jié)論3:如果一個(gè)線程的邏輯單元執(zhí)行完,會(huì)進(jìn)入TERMINATED狀態(tài)渗柿,再次執(zhí)行start()也是不行的个盆。通過上一節(jié)的狀態(tài)轉(zhuǎn)換圖看到,從TERMINATED狀態(tài)并不能回到RUNNABLE狀態(tài)。

三颊亮、sleep()和yield()方法的區(qū)別

  • yield():調(diào)用該方法會(huì)通知CPU調(diào)度器放棄CPU資源柴梆,線程從RUNINIG狀態(tài)轉(zhuǎn)到RUNNABLE狀態(tài)。會(huì)導(dǎo)致線程上下文切換终惑。但如果CPU資源不緊張绍在,調(diào)度器會(huì)忽略yield請求。
  • sleep():調(diào)用該方法會(huì)使得當(dāng)前線程暫停指定的時(shí)間狠鸳,線程從RUNNING狀態(tài)轉(zhuǎn)到BLOCKED狀態(tài)揣苏。但不會(huì)釋放鎖資源。

四件舵、join()方法

我們先從一個(gè)例子說起:

public class ThreadDemo {

    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                System.out.println("t1 thread");
            }
        };

        Thread t2 = new Thread() {
            @Override
            public void run() {
                try {
                    t1.join();
                } catch (Exception e) {}
                System.out.println("t2 thread");
            }
        };

        t1.start();
        t2.start();
        t2.join();
        System.out.println("main thread");
    }
}
t1 thread
t2 thread
main thread

無論輸出多次其結(jié)果都是固定的t1→t2→main卸察。如果去掉join()方法,則三者的順序則不固定铅祸。

當(dāng)前線程Main執(zhí)行中坑质,join線程t2,則Main線程進(jìn)入BLOCKED狀態(tài)临梗,直到t2結(jié)束生命周期或達(dá)到指定時(shí)間涡扼。同樣地,t2線程執(zhí)行中盟庞,join線程t1吃沪,則t2線程會(huì)等到t1線程執(zhí)行完才會(huì)執(zhí)行。

結(jié)論:當(dāng)前執(zhí)行線程join某個(gè)線程之后什猖,該執(zhí)行線程會(huì)等待join線程執(zhí)行完/達(dá)到指定時(shí)間才會(huì)繼續(xù)進(jìn)行執(zhí)行票彪。常見的場景是一個(gè)任務(wù)分割成多個(gè)小任務(wù),等各個(gè)小任務(wù)均執(zhí)行完成后不狮,再執(zhí)行匯總操作降铸。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市摇零,隨后出現(xiàn)的幾起案子推掸,更是在濱河造成了極大的恐慌,老刑警劉巖驻仅,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谅畅,死亡現(xiàn)場離奇詭異,居然都是意外死亡噪服,警方通過查閱死者的電腦和手機(jī)铃彰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來芯咧,“玉大人,你說我怎么就攤上這事【挫” “怎么了邪铲?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長无拗。 經(jīng)常有香客問我带到,道長,這世上最難降的妖魔是什么英染? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任揽惹,我火速辦了婚禮,結(jié)果婚禮上四康,老公的妹妹穿的比我還像新娘搪搏。我一直安慰自己,他們只是感情好闪金,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布疯溺。 她就那樣靜靜地躺著,像睡著了一般哎垦。 火紅的嫁衣襯著肌膚如雪囱嫩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天漏设,我揣著相機(jī)與錄音墨闲,去河邊找鬼。 笑死郑口,一個(gè)胖子當(dāng)著我的面吹牛鸳碧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播潘酗,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼杆兵,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了仔夺?” 一聲冷哼從身側(cè)響起琐脏,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缸兔,沒想到半個(gè)月后日裙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惰蜜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年昂拂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抛猖。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡格侯,死狀恐怖鼻听,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情联四,我是刑警寧澤撑碴,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站朝墩,受9級特大地震影響醉拓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜收苏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一亿卤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鹿霸,春花似錦排吴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至葛闷,卻和暖如春憋槐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背淑趾。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工阳仔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人扣泊。 一個(gè)月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓近范,卻偏偏與公主長得像,于是被迫代替她去往敵國和親延蟹。 傳聞我的和親對象是個(gè)殘疾皇子评矩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容