JAVA面試題 start()和run()詳解
問(wèn)題
面試官:請(qǐng)問(wèn)啟動(dòng)線程是start()還是run()方法,能談?wù)剢幔?/p>
應(yīng)聘者:start()方法
當(dāng)用start()開始一個(gè)線程后,線程就進(jìn)入就緒狀態(tài),使線程所代表的虛擬處理機(jī)處于可運(yùn)行狀態(tài),這意味著它可以由JVM調(diào)度并執(zhí)行。但是這并不意味著線程就會(huì)立即運(yùn)行。只有當(dāng)cpu分配時(shí)間片時(shí),這個(gè)線程獲得時(shí)間片時(shí),才開始執(zhí)行run()方法。start()是方法,它調(diào)用run()方法.而run()方法是你必須重寫的. run()方法中包含的是線程的主體(真正的邏輯)。
繼承Thread類的啟動(dòng)方式
public class ThreadTest {
public static void main(String[] args) {
MyThread t =new MyThread();
t.start();
}
}
class MyThread extends Thread{
@Override
public void run() {
System.out.println("Hello World!");
}
}
實(shí)現(xiàn)Runnable接口的啟動(dòng)方式
public class ThreadTest {
public static void main(String[] args) {
Thread t =new Thread(new MyRunnable());
t.start();
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("Hello World!");
}
}
實(shí)際上這兩種啟動(dòng)線程的方式原理是一樣的。首先都是調(diào)用本地方法啟動(dòng)一個(gè)線程,其次是在這個(gè)線程里執(zhí)行目標(biāo)對(duì)象的run()方法。那么這個(gè)目標(biāo)對(duì)象是什么呢?為了弄明白這個(gè)問(wèn)題,我們來(lái)看看Thread類的run()方法的實(shí)現(xiàn):
public void run() {
if (target != null) {
target.run();
}
}
當(dāng)我們采用實(shí)現(xiàn)Runnable接口的方式來(lái)實(shí)現(xiàn)線程的情況下,在調(diào)用new Thread(Runnable target)構(gòu)造器時(shí),將實(shí)現(xiàn)Runnable接口的類的實(shí)例設(shè)置成了線程要執(zhí)行的主體所屬的目標(biāo)對(duì)象target,當(dāng)線程啟動(dòng)時(shí),這個(gè)實(shí)例的 run()方法就被執(zhí)行了。
當(dāng)我們采用繼承Thread的方式實(shí)現(xiàn)線程時(shí),線程的這個(gè)run()方法被重寫了,所以當(dāng)線程啟動(dòng)時(shí),執(zhí)行的是這個(gè)對(duì)象自身的 run()方法。
總結(jié)起來(lái):如果我們采用的是繼承Thread類的方式,那么這個(gè)target就是線程對(duì)象自身,如果我們采用的是實(shí)現(xiàn)Runnable接口的方式,那么這個(gè)target就是實(shí)現(xiàn)了Runnable接口的類的實(shí)例。
我們?cè)賮?lái)看一道混跡于各大面試公司筆試的題目:
public class EqualsTest {
public static void main(String args[]) {
Thread t = new Thread() {
public void run() {
pong();
}
};
t.run();
System.out.print("ping");
}
static void pong() {
System.out.print("pong");
}
}
這里的標(biāo)準(zhǔn)答案是:pongping
這里直接調(diào)用線程的run方法,就相當(dāng)于調(diào)用普通方法一樣,由上往下執(zhí)行,所以最后的結(jié)果是pongping。但是如果上面改成t.start()之后,這個(gè)結(jié)果就不固定了,因?yàn)檫@里有兩個(gè)線程(其實(shí)還有一個(gè)守護(hù)線程,這里就先忽略),main線程和 t 線程,這兩個(gè)線程獲得cpu的時(shí)間就會(huì)不固定了,誰(shuí)先獲得CPU執(zhí)行權(quán),誰(shuí)就先打印結(jié)果,所以最后的結(jié)果可能pongping也可能是pingpong。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringMVC中@ModelAttribute注解的使用教程
在SpringMVC中,我們可以通過(guò)使用@ModelAttribute注解標(biāo)記方法,實(shí)現(xiàn)類似于Struts2中Preparable攔截器的效果,這篇文章主要給大家介紹了關(guān)于SpringMVC中@ModelAttribute注解使用的相關(guān)資料,需要的朋友可以參考下2021-08-08
Java數(shù)據(jù)庫(kù)連接池技術(shù)的入門教程
這篇文章主要給大家介紹了關(guān)于Java數(shù)據(jù)庫(kù)連接池技術(shù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
Java里得到00:00:00格式的時(shí)分秒的Timestamp
Java里如何得到00:00:00格式的時(shí)分秒的Timestamp ,下面是具體的實(shí)現(xiàn)代碼,需要的朋友可以參考下。2009-09-09
詳解Java的Hibernate框架中的Interceptor和Collection
這篇文章主要介紹了Java的Hibernate框架中的Interceptor和Collection,Hibernate是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下2016-01-01
Java 動(dòng)態(tài)模擬操作系統(tǒng)進(jìn)程調(diào)度算法
這篇文章主要介紹了采用java語(yǔ)言編程模擬N個(gè)進(jìn)程采用動(dòng)態(tài)高優(yōu)先權(quán)優(yōu)先進(jìn)程調(diào)度算法。文中代碼具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下2021-12-12
SpringBatch從入門到精通之StepScope作用域和用法詳解
這篇文章主要介紹了SpringBatch從入門到精通之StepScope作用域和用法詳解,主要包括IOC容器中幾種bean的作用范圍以及可能遇到的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05

