自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試突擊:為什么Start方法不能重復(fù)調(diào)用?而Run方法卻可以?

開(kāi)發(fā) 前端
初學(xué)線程時(shí),總是將 run 方法和 start 方法搞混,雖然二者是完全不同的兩個(gè)方法,但剛開(kāi)始使用時(shí)很難分清,原因就是因?yàn)槌醮问褂脮r(shí)效果貌似是一樣的.

作者 | 磊哥

來(lái)源 | Java面試真題解析(ID:aimianshi666)

轉(zhuǎn)載請(qǐng)聯(lián)系授權(quán)(微信ID:GG_Stone)

初學(xué)線程時(shí),總是將 run 方法和 start 方法搞混,雖然二者是完全不同的兩個(gè)方法,但剛開(kāi)始使用時(shí)很難分清,原因就是因?yàn)槌醮问褂脮r(shí)效果貌似是一樣的,如下代碼所示:

public static void main(String[] args) {
// 創(chuàng)建線程一
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("執(zhí)行線程一");
}
});
// 調(diào)用 run 方法
thread.run();

// 創(chuàng)建線程二
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("執(zhí)行線程二");
}
});
// 調(diào)用 start 方法
thread2.start();
}

以上程序的執(zhí)行結(jié)果如下:

從上述結(jié)果可以看出,二者調(diào)用之后的執(zhí)行效果都是一樣,都可以成功執(zhí)行任務(wù)。但是,如果在執(zhí)行線程的時(shí)候,加上打印當(dāng)前線程的名稱就能看出二者的不同了,如下代碼所示:

public static void main(String[] args) {
// 創(chuàng)建線程一
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// 獲取到當(dāng)前執(zhí)行線程
Thread currThread = Thread.currentThread();
System.out.println("執(zhí)行線程一,線程名:" + currThread.getName());
}
});
// 調(diào)用 run 方法
thread.run();

// 創(chuàng)建線程二
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
// 獲取到當(dāng)前執(zhí)行線程
Thread currThread = Thread.currentThread();
System.out.println("執(zhí)行線程二,線程名:" + currThread.getName());
}
});
// 調(diào)用 start 方法
thread2.start();
}

以上程序的執(zhí)行結(jié)果如下:

從上述結(jié)果我們可以看出:當(dāng)調(diào)用 run 方法時(shí),其實(shí)是調(diào)用當(dāng)前主程序 main 來(lái)執(zhí)行方法體的;而調(diào)用 start 方法才是真正的創(chuàng)建一個(gè)新線程來(lái)執(zhí)行任務(wù)。

區(qū)別

1run 方法和 start 方法的第一個(gè)區(qū)別是:調(diào)用 start 方法是真正開(kāi)啟一個(gè)線程來(lái)執(zhí)行任務(wù),而調(diào)用 run 方法相當(dāng)于執(zhí)行普通方法 run,并不會(huì)開(kāi)啟新線程,如下圖所示:

區(qū)別2

run 方法和 start 方法的第二個(gè)區(qū)別是:run 方法也叫做線程體,它里面包含了具體要執(zhí)行的業(yè)務(wù)代碼,當(dāng)調(diào)用 run 方法時(shí),會(huì)立即執(zhí)行 run 方法中的代碼(如果當(dāng)前線程時(shí)間片未用完);而調(diào)用 start 方法時(shí),是啟動(dòng)一個(gè)線程并將線程的狀態(tài)設(shè)置為就緒狀態(tài)。也就是說(shuō)調(diào)用 start 方法,并不會(huì)立即執(zhí)行。

區(qū)別3

因?yàn)?run 方法是普通方法,而普通方法是可以被多次調(diào)用的,所以 run 方法可以被調(diào)用多次;而 start 方法是創(chuàng)建新線程來(lái)執(zhí)行任務(wù),因?yàn)榫€程只能被創(chuàng)建一次,所以它們的第三個(gè)區(qū)別是:run 方法可以被調(diào)用多次,而 start 方法只能被調(diào)用一次。測(cè)試代碼如下:


// 創(chuàng)建線程一
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// 獲取到當(dāng)前執(zhí)行的線程
Thread currThread = Thread.currentThread();
System.out.println("執(zhí)行線程一,線程名:" + currThread.getName());
}
});
// 調(diào)用 run 方法
thread.run();
// 多次調(diào)用 run 方法
thread.run();

// 創(chuàng)建線程二
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
// 獲取到當(dāng)前執(zhí)行的線程
Thread currThread = Thread.currentThread();
System.out.println("執(zhí)行線程二,線程名:" + currThread.getName());
}
});
// 調(diào)用 start 方法
thread2.start();
// 多次調(diào)用 start 方法
thread2.start();

以上程序的執(zhí)行結(jié)果如下:

從上述結(jié)果可以看出,run 方法多次調(diào)用可用正常執(zhí)行,而第二次調(diào)用 start 方法時(shí)程序就報(bào)錯(cuò)了,提示“IllegalThreadStateException”非法線程狀態(tài)異常。

為什么start不能被重復(fù)調(diào)用?

要找到這個(gè)問(wèn)題的答案,就要查看 start 方法的實(shí)現(xiàn)源碼,它的源碼如下:

從 start 源碼實(shí)現(xiàn)的第一行,我們就可以得到問(wèn)題的答案,因?yàn)?start 方法在執(zhí)行時(shí),會(huì)先判斷當(dāng)前線程的狀態(tài)是不是等于 0,也就是是否為新建狀態(tài) NEW,如果不等于新建狀態(tài),那么就會(huì)拋出“IllegalThreadStateException”非法線程狀態(tài)異常,這就是線程的 start 方法不能被重復(fù)調(diào)用的原因。它的執(zhí)行過(guò)程是:當(dāng)線程調(diào)用了第一個(gè) start 方法之后,線程的狀態(tài)就會(huì)從新建狀態(tài) NEW,變?yōu)榫途w狀態(tài) RUNNABLE,此時(shí)再次調(diào)用 start 方法,JVM 就會(huì)判斷出當(dāng)前的線程已經(jīng)不等于新建狀態(tài),從而拋出 IllegalThreadStateException 非法線程狀態(tài)異常。

總結(jié)

run 方法和 start 方法的主要區(qū)別如下:

  1. 方法性質(zhì)不同:run 是一個(gè)普通方法,而 start 是開(kāi)啟新線程的方法。
  2. 執(zhí)行速度不同:調(diào)用 run 方法會(huì)立即執(zhí)行任務(wù),調(diào)用 start 方法是將線程的狀態(tài)改為就緒狀態(tài),不會(huì)立即執(zhí)行。
  3. 調(diào)用次數(shù)不同:run 方法可以被重復(fù)調(diào)用,而 start 方法只能被調(diào)用一次。

start 方法之所以不能被重復(fù)調(diào)用的原因是,線程的狀態(tài)是不可逆的,Thread 在 start 的實(shí)現(xiàn)源碼中做了判斷,如果線程不是新建狀態(tài) NEW,則會(huì)拋出非法線程狀態(tài)異常 IllegalThreadStateException。

責(zé)任編輯:姜華 來(lái)源: Java面試真題解析
相關(guān)推薦

2020-05-12 08:56:16

Java 線程開(kāi)發(fā)

2022-09-05 15:36:47

線程方法Java

2022-01-11 06:53:23

面試重寫(xiě)重載

2022-07-27 07:36:01

TCP可靠性

2022-01-06 06:58:19

Java 語(yǔ)言 Java 基礎(chǔ)

2022-04-18 07:36:37

TimeUnit線程休眠

2020-12-30 10:04:46

userMapper接口

2022-07-13 07:06:47

HTTPSHTTP協(xié)議

2022-09-20 22:27:08

事務(wù)失效public 修飾

2019-04-08 09:37:30

國(guó)內(nèi)程序員美國(guó)程序員996.ICU

2022-01-24 07:01:20

安全多線程版本

2009-08-26 16:58:12

調(diào)用C# Thread

2022-07-25 07:07:35

TCP客戶端服務(wù)器

2022-01-18 06:59:50

HashMap循環(huán)底層

2022-03-02 07:36:37

池化技術(shù)Java線程池

2021-04-16 17:02:21

數(shù)組C++語(yǔ)言

2022-01-27 07:02:52

JavaHashMap單線程

2022-05-26 09:24:09

volatile懶漢模式

2020-12-15 07:36:12

線程Start Run

2022-01-04 06:56:43

面試Java方法重載
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)