【Java并發(fā)學(xué)習(xí)】之詳解線程的點滴(1)

【Java并發(fā)學(xué)習(xí)】之詳解線程的點滴(1)

前言

在前面的幾個小節(jié)中盔沫,我們粗略地學(xué)習(xí)了線程的基本概念,定義任務(wù)的方式,并且通過Java中的多線程API來驅(qū)動對應(yīng)的任務(wù)漱办,然后學(xué)習(xí)了線程的互斥與同步關(guān)系苇羡,線程之間進(jìn)行資源共享后的同步操作等等一些簡單的內(nèi)容绸吸,可以說鼻弧,線程中的主要內(nèi)容我們已經(jīng)掌握了,然而锦茁,也僅僅只是簡單內(nèi)容攘轩,很多比較細(xì)節(jié)、復(fù)雜的東西在之前我們刻意避開了码俩,接下來的幾個小節(jié)中度帮,我們就來具體地學(xué)習(xí)線程的各個細(xì)節(jié)內(nèi)容

線程的屬性

線程有許多的屬性,比如線程的ID稿存、名字笨篷、優(yōu)先級、狀態(tài)等瓣履,接下來我們就來具體學(xué)習(xí)這些屬性

線程的ID

每個線程都有對應(yīng)的獨一無二的ID率翅,這些ID是由JVM在運行的時候為線程設(shè)置的,用于區(qū)分不同的線程袖迎,并且不對外提供設(shè)置線程ID的接口冕臭,也就是說,在Java中燕锥,我們僅能夠獲取多線程的ID辜贵,而不能設(shè)置線程的ID,訪問代碼如下


    class DetailTask implements Runnable{

        @Override
        public void run() {
            System.out.println("Details : " + Thread.currentThread().getId());
            // 其中Thread.currentThread()用于獲取當(dāng)前執(zhí)行的線程
            // 通過thread.getId()則可以獲取對應(yīng)的線程的ID
        }
    }

線程的名字

在線程比較多的情況下归形,我們會傾向于根據(jù)執(zhí)行不同任務(wù)的不同線程來為其設(shè)置名字托慨,方便在日志以及其他場景中使用到,設(shè)置以及獲取線程的名字操作具體如下


    class DetailTask implements Runnable{

        private static int cnt = 0;
        // 注意這里的代碼是非線程安全的
        @Override
        public void run() {
            Thread.currentThread().setName("Thread " + cnt++); // 設(shè)置線程名字
            System.out.println("Details : " + Thread.currentThread().getName()); // 獲取線程的名字
        }
    }

線程優(yōu)先級

優(yōu)先級是一個比較有價值的概念暇榴,在Java中厚棵,線程之間的調(diào)度采用的是基于時間片的輪轉(zhuǎn)調(diào)度方式,其中在線程進(jìn)行切換跺撼,重新調(diào)度時窟感,調(diào)度的主要依據(jù)就是優(yōu)先級,通常來說歉井,優(yōu)先級比較高的線程柿祈,被調(diào)度的可能性會比較大,也就是說哩至,在單位時間內(nèi)躏嚎,優(yōu)先級高的線程被調(diào)度的次數(shù)會大于優(yōu)先級低的線程

不過,在設(shè)置線程的優(yōu)先級的時候菩貌,需要注意一下幾點

  • 線程的有效優(yōu)先級僅能為 0 - 10 之間的整數(shù)卢佣,其他數(shù)字則會拋出java.lang.IllegalArgumentException
  • 由于不同的操作系統(tǒng)的優(yōu)先級的范圍不一致,而映射到0-10之間則會出現(xiàn)一些意想不到的驚喜箭阶,所以一般在設(shè)置優(yōu)先級的時候虚茶,不能過分依賴于優(yōu)先級戈鲁,盡量只使用Thread.MAX_PRIORITYThread.MIN_PRIORITY以及默認(rèn)的優(yōu)先級嘹叫,分別對應(yīng)的數(shù)值為10,0,1
  • 設(shè)置優(yōu)先級僅僅僅能提高線程被調(diào)度的概率婆殿,也就是僅能提高線程被調(diào)度的次數(shù),但是并不能保證執(zhí)行次數(shù)一定會高罩扇,所以婆芦,不能僅依賴優(yōu)先級來實現(xiàn)如同步、合作之類的操作
  • 優(yōu)先級的設(shè)置必須在線程啟動之前設(shè)置喂饥,也就是必須在thread.start()方法執(zhí)行之前進(jìn)行設(shè)置消约,否則,會采用默認(rèn)的優(yōu)先級员帮,言下之意即不能在run方法中進(jìn)行優(yōu)先級的設(shè)置

    for (int i = 0; i < 10; i++){
        Thread thread = new Thread(task);
        System.out.println("Priority " + thread.getPriority());
        if (i % 2 == 0){
            thread.setPriority(Thread.MIN_PRIORITY); // 設(shè)置優(yōu)先級為最低
        }else {
            thread.setPriority(Thread.MAX_PRIORITY); // 設(shè)置優(yōu)先級為最高
        }
        thread.start();
    }

線程的狀態(tài)

通常來講或粮,線程的數(shù)量是多于CPU的數(shù)量,這也就意味著集侯,為了保證每個線程都能得到執(zhí)行被啼,在特定時刻,總會有線程處于非運行狀態(tài)棠枉,當(dāng)然,Java中線程的狀態(tài)不止這兩種泡挺,具體如下

  • NEW:新建狀態(tài)辈讶,此時線程已經(jīng)被賦予了任務(wù)锦秒,但需要注意的是哈雏,此時執(zhí)行該線程所需要的資源仍未準(zhǔn)備好,是不具備執(zhí)行條件的寡键,也就是在調(diào)用start()方法之前的狀態(tài)
  • RUNNABLE:可運行狀態(tài)媳溺,表明此時該線程已經(jīng)是處于可執(zhí)行的狀態(tài)月幌,這里需要注意的是,可運行狀態(tài)可以是該線程正在執(zhí)行悬蔽,也可能該線程的除了CPU之外的其他資源都已經(jīng)準(zhǔn)備完畢扯躺,只要分配給其CPU就能執(zhí)行。注意是Runnable而不是Run
  • BLOCKED:阻塞狀態(tài)蝎困,線程如果處于該狀態(tài)录语,則表明此時該線程正在等在某個鎖的釋放
  • WAITING:等待狀態(tài),表明此時該線程正在等待某些其他線程的資源禾乘,通常是調(diào)用了Object.wait()澎埠、join()LockSupport.park()這幾個方法
  • TIMED_WAITING:等待超時狀態(tài)始藕,同樣是等待狀態(tài)蒲稳,只是多了個計時器氮趋,通常是調(diào)用了上面幾個方法中帶時間參數(shù)的重載方法
  • TERMINATED:中斷/結(jié)束狀態(tài),表明此時該線程已經(jīng)處于執(zhí)行完畢的狀態(tài)或者是被其他線程或者JVM中斷江耀,結(jié)束其運行

關(guān)于這幾個狀態(tài)的詳細(xì)介紹凭峡,可以參考JDK源碼中的注釋


    /* A thread can be in only one state at a given point in time.
     * These states are virtual machine states which do not reflect
     * any operating system thread states.
     *
     * @since   1.5
     * @see #getState
     */
    public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * 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
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

守護(hù)線程

上面我們主要學(xué)習(xí)了線程的幾個屬性,ID决记、名字摧冀、優(yōu)先級、狀態(tài)等系宫,接下來我們來學(xué)習(xí)一個新的概念索昂,守護(hù)線程

守護(hù)線程是一類特殊的線程,主要的特點如下

  • 被調(diào)度的頻率較低
  • 當(dāng)當(dāng)前系統(tǒng)中的所有非守護(hù)線程結(jié)束時扩借,守護(hù)線程也會結(jié)束椒惨,而且不管正在執(zhí)行什么任務(wù)

基于守護(hù)線程的特點,在使用的時候需要注意潮罪,不能在守護(hù)線程中做一些邏輯比較復(fù)雜的操作康谆,不能做一些比較重要的操作

一個典型的使用守護(hù)線程的例子就是JVM中的垃圾回收器

    
    public static void main(String[] args) {
        Thread daemonTask = new Thread(new DaemonTask());
        daemonTask.setDaemon(true);// 設(shè)置為守護(hù)線程,這里同樣需要注意嫉到,必須在線程啟動之前進(jìn)行設(shè)置
        daemonTask.start();
    }

    class DaemonTask implements Runnable{
        @Override
        public void run() {
            while (true){
                System.out.println("I'm Daemon thread");
            }
        }
    }

總結(jié)

本小計我們主要學(xué)習(xí)了線程的相關(guān)屬性沃暗,包括了ID、名字何恶、優(yōu)先級孽锥、狀態(tài),以及守護(hù)線程的概念和設(shè)置守護(hù)線程的方法细层,線程中的異常處理惜辑,接下來我們將學(xué)習(xí)線程的中斷以及線程的異常處理等等的內(nèi)容

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市疫赎,隨后出現(xiàn)的幾起案子盛撑,更是在濱河造成了極大的恐慌,老刑警劉巖捧搞,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抵卫,死亡現(xiàn)場離奇詭異,居然都是意外死亡实牡,警方通過查閱死者的電腦和手機(jī)陌僵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來创坞,“玉大人碗短,你說我怎么就攤上這事√庹牵” “怎么了偎谁?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵总滩,是天一觀的道長。 經(jīng)常有香客問我巡雨,道長闰渔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任铐望,我火速辦了婚禮冈涧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘正蛙。我一直安慰自己督弓,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布乒验。 她就那樣靜靜地躺著愚隧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锻全。 梳的紋絲不亂的頭發(fā)上狂塘,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天,我揣著相機(jī)與錄音鳄厌,去河邊找鬼荞胡。 笑死,一個胖子當(dāng)著我的面吹牛部翘,可吹牛的內(nèi)容都是我干的硝训。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼赘风!你這毒婦竟也來了夹囚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤邀窃,失蹤者是張志新(化名)和其女友劉穎荸哟,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞬捕,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡鞍历,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了肪虎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片劣砍。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖扇救,靈堂內(nèi)的尸體忽然破棺而出刑枝,到底是詐尸還是另有隱情香嗓,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布装畅,位于F島的核電站靠娱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏掠兄。R本人自食惡果不足惜像云,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蚂夕。 院中可真熱鬧迅诬,春花似錦、人聲如沸双抽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽牍汹。三九已至铐维,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間慎菲,已是汗流浹背嫁蛇。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留露该,地道東北人睬棚。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像解幼,于是被迫代替她去往敵國和親抑党。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,851評論 2 361

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