常用創(chuàng)建線程的兩種方式(3)

概要

線程作為獨(dú)立調(diào)度運(yùn)行和分派的基本單位银室,很明顯的一個(gè)特征便是可運(yùn)行的偏化。Runnable接口便是對(duì)可被調(diào)度運(yùn)行進(jìn)行了抽象聲明盈蛮。本章主要內(nèi)容如下:

  • 線程構(gòu)造函數(shù)介紹
  • Thread和Runnable的區(qū)別與聯(lián)系
  • 創(chuàng)建線程示例

線程構(gòu)造函數(shù)介紹

    /**
     * 無(wú)參構(gòu)造函數(shù)娘侍,常用
     */
    public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }

    /**
     * 需要參數(shù)Runnable對(duì)象構(gòu)造函數(shù)着降,常用
     */
    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }

    Thread(Runnable target, AccessControlContext acc) {
        init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
    }

    public Thread(ThreadGroup group, Runnable target) {
        init(group, target, "Thread-" + nextThreadNum(), 0);
    }

    /**
     * 線程名稱差油,常用
     */
    public Thread(String name) {
        init(null, null, name, 0);
    }

    public Thread(ThreadGroup group, String name) {
        init(group, null, name, 0);
    }

    /**
     * 常用
     */
    public Thread(Runnable target, String name) {
        init(null, target, name, 0);
    }

創(chuàng)建線程的時(shí)候常用無(wú)參和設(shè)置線程名、設(shè)置Runnable對(duì)象及組合的方式任洞。常見(jiàn)的有Thread()蓄喇、Thread(Runnable target)、Thread(String name)和Thread(Runnable target, String name)交掏,設(shè)置線程組的方式比較少見(jiàn)妆偏,除非真的有必要進(jìn)行分組管理,系統(tǒng)啟動(dòng)的時(shí)候會(huì)設(shè)置系統(tǒng)線程組盅弛、main線程組钱骂。

線程init初始化方法

java.lang.Thread

    /**
     * Initializes a Thread.
     *
     * @param g 線程組
     * @param target 可被調(diào)度運(yùn)行對(duì)象
     * @param name 線程名
     * @param stackSize 線程堆棧大小,0表示忽略
     * @param acc 線程內(nèi)部訪問(wèn)控制
     * @param inheritThreadLocals 是否繼承線程本地變量
     */
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }
        //設(shè)置線程名稱
        this.name = name;

        Thread parent = currentThread();
        //默認(rèn)情況下jvm不開(kāi)啟安全管理器
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            /* Determine if it's an applet or not */

            /* If there is a security manager, ask the security manager
               what to do. */
            if (security != null) {
                g = security.getThreadGroup();
            }

            /* If the security doesn't have a strong opinion of the matter
               use the parent thread group. */
            if (g == null) {
                //不是通過(guò)設(shè)置線程組的方式創(chuàng)建線程挪鹏,默認(rèn)歸屬于父線程的線程組
                g = parent.getThreadGroup();
            }
        }

        /* checkAccess regardless of whether or not threadgroup is
           explicitly passed in. */
        g.checkAccess();

        /*
         * Do we have the required permissions?
         */
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }

        g.addUnstarted();
        //線程組賦值
        this.group = g;
        //是否守護(hù)線程繼承默認(rèn)繼承自父線程
        this.daemon = parent.isDaemon();
        //線程優(yōu)先級(jí)见秽,也是繼承自父線程,默認(rèn)為5
        this.priority = parent.getPriority();
        //線程對(duì)應(yīng)類加載器
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        //Runnable實(shí)例讨盒,相當(dāng)于要運(yùn)行的task
        this.target = target;
        setPriority(priority);
        //繼承父線程inheritThreadLocals
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

        /* Set thread ID */
        tid = nextThreadID();
    }

除了安全管理器的訪問(wèn)檢查稍微陌生(自行baidu解取、google),線程初始化相對(duì)比較簡(jiǎn)單返顺,做了線程相關(guān)屬性的初始化操作禀苦。

Thread和Runnable的區(qū)別與聯(lián)系

Runnable是接口,用于聲明Runnable實(shí)例是可以被線程調(diào)度運(yùn)行的创南,只定義了一個(gè)run()方法:

public interface Runnable {
    public abstract void run();
}

可以通過(guò)public Thread(Runnable target)伦忠、public Thread(Runnable target, String name)構(gòu)造函數(shù)進(jìn)行創(chuàng)建線程省核。
Thread是類稿辙,實(shí)現(xiàn)了Runnable接口,這也說(shuō)明了線程是可以被獨(dú)立調(diào)度運(yùn)行和分派的气忠。

public class Thread implements Runnable {
    ...

    /**
     * 實(shí)現(xiàn)Runnable邻储,線程CPU被調(diào)度后代碼執(zhí)行入口
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

    ...
}

從代碼上看赋咽,直接通過(guò)無(wú)參構(gòu)造函數(shù)創(chuàng)建線程并啟動(dòng),實(shí)際上run()就相當(dāng)于一個(gè)空方法吨娜。因此脓匿,如果不以Runnable實(shí)例創(chuàng)建線程,則應(yīng)該通過(guò)繼承Thread類覆蓋run()方法的方式創(chuàng)建線程宦赠。接下來(lái)是常見(jiàn)的創(chuàng)建線程的兩種方式陪毡。

創(chuàng)建線程示例

  • 繼承Thread類覆蓋run()方法的方式
public class Hello extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " Hello word !");
    }
}
//調(diào)用
public class ThreadCreate {
    public static void main(String[] args) {
        //啟動(dòng)三個(gè)線程
        for (int i = 0; i < 3; i++) {
            //一定要注意的是調(diào)用start()方法啟動(dòng)線程,而非調(diào)用run()方法
            new Hello().start();
        }
    }
}

運(yùn)行結(jié)果:

Thread-0 Hello word !
Thread-2 Hello word !
Thread-1 Hello word !

  • 實(shí)現(xiàn)Runnable方式創(chuàng)建線程
    上邊的代碼修改為實(shí)現(xiàn)Runnable方式:
public static class Hello implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " Hello word !");
    }
}

public class ThreadCreate {
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new Thread(new Hello()).start();
        }
    }
}

運(yùn)行結(jié)果:

Thread-0 Hello word !
Thread-2 Hello word !
Thread-1 Hello word !

選擇哪種方式

通過(guò)繼承的方式勾扭,Thread實(shí)現(xiàn)Runnable接口毡琉,即Thread是Runnable實(shí)例。從Thread實(shí)現(xiàn)Runnable接口代碼片段看妙色,如果target(Runnable實(shí)例)為空桅滋,run()相當(dāng)于是一個(gè)空方法,繼承覆蓋的方式實(shí)際上就是重新實(shí)現(xiàn)了Runnable接口身辨。
target被多個(gè)線程共享丐谋,同一個(gè)任務(wù)由多個(gè)線程完成,發(fā)揮多線程的優(yōu)勢(shì)煌珊。拿Thread當(dāng)Runnable實(shí)例感覺(jué)上總是有些別扭号俐。
所以,從面向接口編程的角度看推薦直接實(shí)現(xiàn)Runnable的方式創(chuàng)建線程定庵。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末萧落,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子洗贰,更是在濱河造成了極大的恐慌找岖,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件敛滋,死亡現(xiàn)場(chǎng)離奇詭異许布,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)绎晃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門蜜唾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人庶艾,你說(shuō)我怎么就攤上這事袁余。” “怎么了咱揍?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵颖榜,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)掩完,這世上最難降的妖魔是什么噪漾? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮且蓬,結(jié)果婚禮上欣硼,老公的妹妹穿的比我還像新娘。我一直安慰自己恶阴,他們只是感情好诈胜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著冯事,像睡著了一般耘斩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上桅咆,一...
    開(kāi)封第一講書(shū)人閱讀 51,488評(píng)論 1 302
  • 那天括授,我揣著相機(jī)與錄音,去河邊找鬼岩饼。 笑死荚虚,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的籍茧。 我是一名探鬼主播版述,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼寞冯!你這毒婦竟也來(lái)了渴析?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤吮龄,失蹤者是張志新(化名)和其女友劉穎俭茧,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體漓帚,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡母债,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了尝抖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毡们。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖昧辽,靈堂內(nèi)的尸體忽然破棺而出衙熔,到底是詐尸還是另有隱情,我是刑警寧澤搅荞,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布红氯,位于F島的核電站框咙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏脖隶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一暇检、第九天 我趴在偏房一處隱蔽的房頂上張望产阱。 院中可真熱鬧,春花似錦块仆、人聲如沸构蹬。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)庄敛。三九已至,卻和暖如春科汗,著一層夾襖步出監(jiān)牢的瞬間藻烤,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工头滔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怖亭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓坤检,卻偏偏與公主長(zhǎng)得像兴猩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子早歇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理倾芝,服務(wù)發(fā)現(xiàn),斷路器箭跳,智...
    卡卡羅2017閱讀 134,656評(píng)論 18 139
  • 進(jìn)程和線程 進(jìn)程 所有運(yùn)行中的任務(wù)通常對(duì)應(yīng)一個(gè)進(jìn)程,當(dāng)一個(gè)程序進(jìn)入內(nèi)存運(yùn)行時(shí),即變成一個(gè)進(jìn)程.進(jìn)程是處于運(yùn)行過(guò)程中...
    小徐andorid閱讀 2,808評(píng)論 3 53
  • Java多線程學(xué)習(xí) [-] 一擴(kuò)展javalangThread類 二實(shí)現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 2,957評(píng)論 1 18
  • 本文主要講了java中多線程的使用方法晨另、線程同步、線程數(shù)據(jù)傳遞谱姓、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法拯刁、概述等。 首先講...
    李欣陽(yáng)閱讀 2,454評(píng)論 1 15
  • 一個(gè)好的游戲會(huì)讓人感到輕松愉快逝段,是排解壓力的方式垛玻,有的游戲能讓人收獲友誼,有的游戲能夠提高某種能力奶躯,比如邏輯思維帚桩、...
    Molly_0閱讀 423評(píng)論 0 0