Java并發(fā)——this與Thread.currentThread()的區(qū)別

引言

首先來看下下面這段代碼赛蔫。這是一段簡單的中斷線程的示例代碼纲仍。

public class Test {

    static class Runner extends Thread {
        @Override
        public void run() {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("Interruted!");
                    break;
                }
            }
        }
    }
    
    public static void main(String[] args) {
        Runner runner = new Runner();
        runner.start();
        runner.interrupt();
    }

}

其中的 “Thread.currentThread()” 引發(fā)了我的思考:“既然該Runner的對象正在作為線程運行雏赦,那 this 和 Thread.currentThread() 不也就是同一個對象灌侣,為什么不直接用this呢后频?眉抬,相比之下this更加簡短吴藻÷髋溃”

在上面這段段代碼中,將 Thread.currentThread() 替換成 this沟堡,是等同的侧但,運行結(jié)果相同,能正常退出航罗。

而下面代碼禀横,this 和 Thread.currentThread() 則運行結(jié)果則不同。this 會出現(xiàn)死循環(huán)粥血,無法退出柏锄;Thread.currentThread() 能正常退出。

public class Test {

    static class Runner extends Thread {
        @Override
        public void run() {
            while (true) {
                if (this.isInterrupted()) {
                    System.out.println("Interruted!");
                    break;
                }
            }
        }
    }

    public static void main(String[] args) {
        Runner runner = new Runner();
        Thread thread = new Thread(runner);
        thread.start();
        thread.interrupt();
    }

}

這說明 this 和 Thread.currentThread() 并不能完全等同复亏。

其原因主要跟 Thread 類的內(nèi)部實現(xiàn)有關(guān)趾娃。

正文

在直接揭秘兩者區(qū)別之前,先來了解下 Thread 類的內(nèi)部實現(xiàn)缔御。

Runner的中實現(xiàn)了構(gòu)造函數(shù)抬闷,main方法中只創(chuàng)建了 runner 實例,并沒有啟動線程耕突。

public class Test {
    static class Runner extends Thread {
        public Runner() {
            System.out.println("Thread.currentThread().getName()=" + Thread.currentThread().getName());
            System.out.println("Thread.currentThread().isAlive()=" + Thread.currentThread().isAlive());
            System.out.println("this.getName=" + this.getName());
            System.out.println("this.isAlive()=" + this.isAlive());
        }
    }

    public static void main(String[] args) {
        Runner runner = new Runner();
    }
}

/** output
Thread.currentThread().getName()=main
Thread.currentThread().isAlive()=true
this.getName=Thread-0
this.isAlive()=false
**/

根據(jù)前兩行輸出笤成,可以看出评架,“當(dāng)前的執(zhí)行線程是 main 線程,并且處于運行狀態(tài)”炕泳,容易理解纵诞。

再看后兩行輸出,this 指向的是新建的 runner 實例喊崖,該實例的 name 屬性為 “Thread-0”挣磨,并且沒有運行。沒有運行很容易理解荤懂,因為沒有執(zhí)行 runner.start() 方法茁裙。關(guān)于 name 屬性為何是 “Thread-0”,這是在創(chuàng)建 Thread 實例時节仿,初始化的名字晤锥。

下面是 Thread類 的構(gòu)造函數(shù),其中 init() 方法第三個參數(shù)為線程的默認(rèn)名字廊宪。生成名稱的規(guī)則是:“Thread-”加上創(chuàng)建的線程的個數(shù)(第幾個)矾瘾。默認(rèn)從0開始,由于main線程是默認(rèn)就有的箭启,所以并不計數(shù) 壕翩。

public Thread() {
    init(null, null, "Thread-" + nextThreadNum(), 0);
}

所以 runner.getname() 得到的結(jié)果是 "Thread-0"。


接下來再看一段代碼傅寡。新建 Runner 實例對象 runner放妈。由于 Runner 是 Thread 的子類,并且 Thread 實現(xiàn)了 Runnable 接口荐操,所以可以作為 Thread 類的構(gòu)造函數(shù)參數(shù)傳入芜抒。將 runner 作為構(gòu)造函數(shù)參數(shù)傳入,創(chuàng)建 Thread 實例對象 thread托启,啟動 thread宅倒。

public class Test {
    static class Runner extends Thread {
        @Override
        public void run() {
            System.out.println("Thread.currentThread().getName()=" + Thread.currentThread().getName());
            System.out.println("Thread.currentThread().isAlive()=" + Thread.currentThread().isAlive());
            System.out.println("this.getName=" + this.getName());
            System.out.println("this.isAlive()=" + this.isAlive());
        }
    }

    public static void main(String[] args) {
        Runner runner = new Runner();
        Thread thread = new Thread(runner);
        thread.start();
    }
}

/** output
Thread.currentThread().getName()=Thread-1
Thread.currentThread().isAlive()=true
this.getName=Thread-0
this.isAlive()=false
**/

首先看下前兩行輸出,可看出 Thread.currentThread() 指向 thread 對象屯耸,其name為“Thread-1”(第二個被創(chuàng)建)拐迁,并且處于運行狀態(tài)。

再來看看后兩行輸出肩民,可看出 this 指向的是 runner 對象唠亚,其name為“Thread-0”,并且沒有運行持痰。

為什么 this 不是指向 thread 呢灶搜??? 不是 thread 在運行嗎割卖?前酿??

其原因在于 Thread thread = new Thread(runner)將 runner 對象綁定到 thread 對象的一個 pravite 變量target 上鹏溯,在 thread 被執(zhí)行的時候即 thread.run() 被調(diào)用的時候罢维,它會調(diào)用 target.run() 方法,也就是說它是直接調(diào)用 runner 對象的run方法丙挽。

再確切的說肺孵,在run方法被執(zhí)行的時候,this.getName() 實際上返回的是 target.getName()颜阐,而Thread.currentThread().getName() 實際上是 thread.getName()平窘。

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

@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

總結(jié)

正在執(zhí)行線程中的 this 對象并非就一定是該執(zhí)行線程,因為執(zhí)行線程的 run方法 可能是直接調(diào)用 其他Runnabel對象的 run() 方法凳怨。

個人看法瑰艘,不要在線程中用 this 來表示當(dāng)前運行線程,不可靠肤舞。

參考文獻

  1. Java多線程之this與Thread.currentThread()的區(qū)別——java多線程編程核心技術(shù)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末紫新,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子李剖,更是在濱河造成了極大的恐慌芒率,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件篙顺,死亡現(xiàn)場離奇詭異敲董,居然都是意外死亡,警方通過查閱死者的電腦和手機慰安,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來聪铺,“玉大人化焕,你說我怎么就攤上這事×逄蓿” “怎么了撒桨?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長键兜。 經(jīng)常有香客問我凤类,道長,這世上最難降的妖魔是什么普气? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任谜疤,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘夷磕。我一直安慰自己履肃,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布坐桩。 她就那樣靜靜地躺著尺棋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪绵跷。 梳的紋絲不亂的頭發(fā)上膘螟,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音碾局,去河邊找鬼荆残。 笑死,一個胖子當(dāng)著我的面吹牛擦俐,可吹牛的內(nèi)容都是我干的脊阴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蚯瞧,長吁一口氣:“原來是場噩夢啊……” “哼嘿期!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起埋合,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤备徐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后甚颂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜜猾,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年振诬,在試婚紗的時候發(fā)現(xiàn)自己被綠了蹭睡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡赶么,死狀恐怖肩豁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辫呻,我是刑警寧澤清钥,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站放闺,受9級特大地震影響祟昭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜怖侦,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一篡悟、第九天 我趴在偏房一處隱蔽的房頂上張望谜叹。 院中可真熱鬧,春花似錦恰力、人聲如沸叉谜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽停局。三九已至,卻和暖如春香府,著一層夾襖步出監(jiān)牢的瞬間董栽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工企孩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留锭碳,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓勿璃,卻偏偏與公主長得像擒抛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子补疑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理歧沪,服務(wù)發(fā)現(xiàn),斷路器莲组,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • 單任務(wù) 單任務(wù)的特點是排隊執(zhí)行诊胞,也就是同步,就像再cmd輸入一條命令后锹杈,必須等待這條命令執(zhí)行完才可以執(zhí)行下一條命令...
    Steven1997閱讀 1,178評論 0 6
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法撵孤,類相關(guān)的語法,內(nèi)部類的語法竭望,繼承相關(guān)的語法邪码,異常的語法,線程的語...
    子非魚_t_閱讀 31,639評論 18 399
  • Java多線程學(xué)習(xí) [-] 一擴展javalangThread類 二實現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 2,959評論 1 18
  • 環(huán)境:ubuntu14.04+opencv2.4.11 步驟 1.在/home/renye/allKindOfLi...
    Renyye閱讀 257評論 0 0