Java程序員面試題集合
AVA程序員廣義上是指一群以JAVA為謀生手段的軟件開(kāi)發(fā)人員。狹義的說(shuō),是指擁有SUN公司JAVA認(rèn)證的程序員。那程序員在面試的時(shí)候大概會(huì)碰到什么樣的面試問(wèn)題呢?一起來(lái)看看。
1 什么是線(xiàn)程?
線(xiàn)程是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位,它被包含在進(jìn)程之中,是進(jìn)程中的實(shí)際運(yùn)作單位。程序員可以通過(guò)它進(jìn)行多處理器編程,你可以使用多線(xiàn)程對(duì)運(yùn)算密集型任務(wù)提速。比如,如果一個(gè)線(xiàn)程完成一個(gè)任務(wù)要100毫秒,那么用十個(gè)線(xiàn)程完成改任務(wù)只需10毫秒。Java在語(yǔ)言層面對(duì)多線(xiàn)程提供了卓越的支持,它也是一個(gè)很好的賣(mài)點(diǎn)。欲了解更多詳細(xì)信息請(qǐng)點(diǎn)擊這里。
2 線(xiàn)程和進(jìn)程有什么區(qū)別?
線(xiàn)程是進(jìn)程的子集,一個(gè)進(jìn)程可以有很多線(xiàn)程,每條線(xiàn)程并行執(zhí)行不同的任務(wù)。不同的進(jìn)程使用不同的內(nèi)存空間,而所有的線(xiàn)程共享一片相同的內(nèi)存空間。別把它和棧內(nèi)存搞混,每個(gè)線(xiàn)程都擁有單獨(dú)的棧內(nèi)存用來(lái)存儲(chǔ)本地?cái)?shù)據(jù)。更多詳細(xì)信息請(qǐng)點(diǎn)擊這里。
在語(yǔ)言層面有兩種方式。ng.Thread 類(lèi)的實(shí)例就是一個(gè)線(xiàn)程但是它需要調(diào)用ng.Runnable接口來(lái)執(zhí)行,由于線(xiàn)程類(lèi)本身就是調(diào)用的Runnable接口所以你可以繼承ng.Thread 類(lèi)或者直接調(diào)用Runnable接口來(lái)重寫(xiě)run方法實(shí)現(xiàn)線(xiàn)程。更多詳細(xì)信息請(qǐng)點(diǎn)擊這里.
3 用Runnable還是Thread?
這個(gè)問(wèn)題是上題的后續(xù),大家都知道我們可以通過(guò)繼承Thread類(lèi)或者調(diào)用Runnable接口來(lái)實(shí)現(xiàn)線(xiàn)程,問(wèn)題是,那個(gè)方法更好呢?什么情況下使用它?這個(gè)問(wèn)題很容易回答,如果你知道Java不支持類(lèi)的多重繼承,但允許你調(diào)用多個(gè)接口。所以如果你要繼承其他類(lèi),當(dāng)然是調(diào)用Runnable接口好了。更多詳細(xì)信息請(qǐng)點(diǎn)擊這里。
4 Thread 類(lèi)中的start 和 run 方法有什么區(qū)別?
這個(gè)問(wèn)題經(jīng)常被問(wèn)到,但還是能從此區(qū)分出面試者對(duì)Java線(xiàn)程模型的`理解程度。start方法被用來(lái)啟動(dòng)新創(chuàng)建的線(xiàn)程,而且start內(nèi)部調(diào)用了run方法,這和直接調(diào)用run方法的效果不一樣。當(dāng)你調(diào)用run方法的時(shí)候,只會(huì)是在原來(lái)的線(xiàn)程中調(diào)用,沒(méi)有新的線(xiàn)程啟動(dòng),start方法才會(huì)啟動(dòng)新線(xiàn)程。更多討論請(qǐng)點(diǎn)擊這里
5 Java中Runnable和Callable有什么不同?
Runnable和Callable都代表那些要在不同的線(xiàn)程中執(zhí)行的任務(wù)。Runnable從JDK1.0開(kāi)始就有了,Callable是在JDK1.5增加的。它們的主要區(qū)別是Callable的 call 方法可以返回值和拋出異常,而Runnable的run方法沒(méi)有這些功能。Callable可以返回裝載有計(jì)算結(jié)果的Future對(duì)象。我的博客有更詳細(xì)的說(shuō)明。
6 Java中CyclicBarrier 和 CountDownLatch有什么不同?
CyclicBarrier 和 CountDownLatch 都可以用來(lái)讓一組線(xiàn)程等待其它線(xiàn)程。與 CyclicBarrier 不同的是,CountdownLatch 不能重新使用。點(diǎn)此查看更多信息和示例代碼。
7 Java內(nèi)存模型是什么?
Java內(nèi)存模型規(guī)定和指引Java程序在不同的內(nèi)存架構(gòu)、CPU和操作系統(tǒng)間有確定性地行為。它在多線(xiàn)程的情況下尤其重要。Java內(nèi)存模型對(duì)一個(gè)線(xiàn)程所做的變動(dòng)能被其它線(xiàn)程可見(jiàn)提供了保證,它們之間是先行發(fā)生關(guān)系。這個(gè)關(guān)系定義了一些規(guī)則讓程序員在并發(fā)編程時(shí)思路更清晰。比如,先行發(fā)生關(guān)系確保了:
線(xiàn)程內(nèi)的代碼能夠按先后順序執(zhí)行,這被稱(chēng)為程序次序規(guī)則。
對(duì)于同一個(gè)鎖,一個(gè)解鎖操作一定要發(fā)生在時(shí)間上后發(fā)生的另一個(gè)鎖定操作之前,也叫做管程鎖定規(guī)則。
前一個(gè)對(duì)volatile的寫(xiě)操作在后一個(gè)volatile的讀操作之前,也叫volatile變量規(guī)則。
一個(gè)線(xiàn)程內(nèi)的任何操作必需在這個(gè)線(xiàn)程的start調(diào)用之后,也叫作線(xiàn)程啟動(dòng)規(guī)則。
一個(gè)線(xiàn)程的所有操作都會(huì)在線(xiàn)程終止之前,線(xiàn)程終止規(guī)則。
一個(gè)對(duì)象的終結(jié)操作必需在這個(gè)對(duì)象構(gòu)造完成之后,也叫對(duì)象終結(jié)規(guī)則。
可傳遞性
我強(qiáng)烈建議大家閱讀《Java并發(fā)編程實(shí)踐》第十六章來(lái)加深對(duì)Java內(nèi)存模型的理解。
8 Java中的volatile 變量是什么?
volatile是一個(gè)特殊的修飾符,只有成員變量才能使用它。在Java并發(fā)程序缺少同步類(lèi)的情況下,多線(xiàn)程對(duì)成員變量的操作對(duì)其它線(xiàn)程是透明的。volatile變量可以保證下一個(gè)讀取操作會(huì)在前一個(gè)寫(xiě)操作之后發(fā)生,就是上一題的volatile變量規(guī)則。點(diǎn)擊這里查看更多volatile的相關(guān)內(nèi)容。
9 什么是線(xiàn)程安全?Vector是一個(gè)線(xiàn)程安全類(lèi)嗎? (詳見(jiàn)這里)
如果你的代碼所在的進(jìn)程中有多個(gè)線(xiàn)程在同時(shí)運(yùn)行,而這些線(xiàn)程可能會(huì)同時(shí)運(yùn)行這段代碼。如果每次運(yùn)行結(jié)果和單線(xiàn)程運(yùn)行的結(jié)果是一樣的,而且其他的變量的值也和預(yù)期的是一樣的,就是線(xiàn)程安全的。一個(gè)線(xiàn)程安全的計(jì)數(shù)器類(lèi)的同一個(gè)實(shí)例對(duì)象在被多個(gè)線(xiàn)程使用的情況下也不會(huì)出現(xiàn)計(jì)算失誤。很顯然你可以將集合類(lèi)分成兩組,線(xiàn)程安全和非線(xiàn)程安全的。Vector 是用同步方法來(lái)實(shí)現(xiàn)線(xiàn)程安全的, 而和它相似的ArrayList不是線(xiàn)程安全的。
10Java中什么是競(jìng)態(tài)條件? 舉個(gè)例子說(shuō)明。
競(jìng)態(tài)條件會(huì)導(dǎo)致程序在并發(fā)情況下出現(xiàn)一些bugs。多線(xiàn)程對(duì)一些資源的競(jìng)爭(zhēng)的時(shí)候就會(huì)產(chǎn)生競(jìng)態(tài)條件,如果首先要執(zhí)行的程序競(jìng)爭(zhēng)失敗排到后面執(zhí)行了,那么整個(gè)程序就會(huì)出現(xiàn)一些不確定的bugs。這種bugs很難發(fā)現(xiàn)而且會(huì)重復(fù)出現(xiàn),因?yàn)榫(xiàn)程間的隨機(jī)競(jìng)爭(zhēng)。一個(gè)例子就是無(wú)序處理,詳見(jiàn)答案。
Java提供了很豐富的API但沒(méi)有為停止線(xiàn)程提供API。JDK 1.0本來(lái)有一些像stop, suspend 和 resume的控制方法但是由于潛在的死鎖威脅因此在后續(xù)的JDK版本中他們被棄用了,之后Java API的設(shè)計(jì)者就沒(méi)有提供一個(gè)兼容且線(xiàn)程安全的方法來(lái)停止一個(gè)線(xiàn)程。當(dāng)run 或者 call 方法執(zhí)行完的時(shí)候線(xiàn)程會(huì)自動(dòng)結(jié)束,如果要手動(dòng)結(jié)束一個(gè)線(xiàn)程,你可以用volatile 布爾變量來(lái)退出run方法的循環(huán)或者是取消任務(wù)來(lái)中斷線(xiàn)程。點(diǎn)擊這里查看示例代碼。
這是我在一次面試中遇到的一個(gè)很刁鉆的Java面試題, 簡(jiǎn)單的說(shuō),如果異常沒(méi)有被捕獲該線(xiàn)程將會(huì)停止執(zhí)行。Thread.UncaughtExceptionHandler是用于處理未捕獲異常造成線(xiàn)程突然中斷情況的一個(gè)內(nèi)嵌接口。當(dāng)一個(gè)未捕獲異常將造成線(xiàn)程中斷的時(shí)候JVM會(huì)使用Thread.getUncaughtExceptionHandler來(lái)查詢(xún)線(xiàn)程的UncaughtExceptionHandler并將線(xiàn)程和異常作為參數(shù)傳遞給handler的uncaughtException方法進(jìn)行處理。
11Java中notify 和 notifyAll有什么區(qū)別?
12為什么wait, notify 和 notifyAll這些方法不在thread類(lèi)里面?
13什么是ThreadLocal變量?
ThreadLocal是Java里一種特殊的變量。每個(gè)線(xiàn)程都有一個(gè)ThreadLocal就是每個(gè)線(xiàn)程都擁有了自己獨(dú)立的一個(gè)變量,競(jìng)爭(zhēng)條件被徹底消除了。它是為創(chuàng)建代價(jià)高昂的對(duì)象獲取線(xiàn)程安全的好方法,比如你可以用ThreadLocal讓SimpleDateFormat變成線(xiàn)程安全的,因?yàn)槟莻(gè)類(lèi)創(chuàng)建代價(jià)高昂且每次調(diào)用都需要?jiǎng)?chuàng)建不同的實(shí)例所以不值得在局部范圍使用它,如果為每個(gè)線(xiàn)程提供一個(gè)自己獨(dú)有的變量拷貝,將大大提高效率。首先,通過(guò)復(fù)用減少了代價(jià)高昂的對(duì)象的創(chuàng)建個(gè)數(shù)。其次,你在沒(méi)有使用高代價(jià)的同步或者不變性的情況下獲得了線(xiàn)程安全。線(xiàn)程局部變量的另一個(gè)不錯(cuò)的例子是ThreadLocalRandom類(lèi),它在多線(xiàn)程環(huán)境中減少了創(chuàng)建代價(jià)高昂的Random對(duì)象的個(gè)數(shù)。查看答案了解更多。
14什么是FutureTask?
在Java并發(fā)程序中FutureTask表示一個(gè)可以取消的異步運(yùn)算。它有啟動(dòng)和取消運(yùn)算、查詢(xún)運(yùn)算是否完成和取回運(yùn)算結(jié)果等方法。只有當(dāng)運(yùn)算完成的時(shí)候結(jié)果才能取回,如果運(yùn)算尚未完成get方法將會(huì)阻塞。一個(gè)FutureTask對(duì)象可以對(duì)調(diào)用了Callable和Runnable的對(duì)象進(jìn)行包裝,由于FutureTask也是調(diào)用了Runnable接口所以它可以提交給Executor來(lái)執(zhí)行。
【Java程序員面試題】相關(guān)文章:
Java程序員面試題詳解01-02
Java程序員的10道XML面試題03-01
Java經(jīng)典面試題05-06
java面試題01-31
java學(xué)習(xí):Java面試題和答案07-23
java面試題匯總01-03
java基礎(chǔ)面試題02-26
JAVA經(jīng)典算法面試題01-06
Java面試題集07-19