1) 什么是線程?
線程是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位,它被包含在進(jìn)程之中,是進(jìn)程中的實際運(yùn)作單位。程序員可以通過它進(jìn)行多處理器編程,你可以使用多線程對運(yùn)算密集型任務(wù)提速。比如,如果一個線程完成一個任務(wù)要100毫秒,那么用十個線程完成該任務(wù)只需10毫秒。
2) 線程和進(jìn)程有什么區(qū)別?
一個進(jìn)程是一個獨立(self contained)的運(yùn)行環(huán)境,它可以被看作一個程序或者一個應(yīng)用。而線程是在進(jìn)程中執(zhí)行的一個任務(wù)。線程是進(jìn)程的子集,一個進(jìn)程可以有很多線程,每條線程并行執(zhí)行不同的任務(wù)。不同的進(jìn)程使用不同的內(nèi)存空間,而所有的線程共享一片相同的內(nèi)存空間。別把它和棧內(nèi)存搞混,每個線程都擁有單獨的棧內(nèi)存用來存儲本地數(shù)據(jù)。
3) 如何在Java中實現(xiàn)線程?
有兩種創(chuàng)建線程的方法:一是實現(xiàn)Runnable接口,然后將它傳遞給Thread的構(gòu)造函數(shù),創(chuàng)建一個Thread對象;二是直接繼承Thread類。
4) 用Runnable還是Thread?
這個問題是上題的后續(xù),大家都知道我們可以通過繼承Thread類或者調(diào)用Runnable接口來實現(xiàn)線程,問題是,那個方法更好呢?什么情況下使用它?這個問題很容易回答,如果你知道Java不支持類的多重繼承,但允許你調(diào)用多個接口。所以如果你要繼承其他類,當(dāng)然是調(diào)用Runnable接口好了。更多詳細(xì)信息請點擊這里。
5) Thread 類中的start() 和 run() 方法有什么區(qū)別?
start()方法被用來啟動新創(chuàng)建的線程,使該被創(chuàng)建的線程狀態(tài)變?yōu)榭蛇\(yùn)行狀態(tài)。當(dāng)你調(diào)用run()方法的時候,只會是在原來的線程中調(diào)用,沒有新的線程啟動,start()方法才會啟動新線程。如果我們調(diào)用了Thread的run()方法,它的行為就會和普通的方法一樣,直接運(yùn)行run()方法。為了在新的線程中執(zhí)行我們的代碼,必須使用Thread.start()方法。
7) Java中Runnable和Callable有什么不同?
Runnable和Callable都代表那些要在不同的線程中執(zhí)行的任務(wù)。Runnable從JDK1.0開始就有了,Callable是在JDK1.5增加的。它們的主要區(qū)別是Callable的 call() 方法可以返回值和拋出異常,而Runnable的run()方法沒有這些功能。Callable可以返回裝載有計算結(jié)果的Future對象。
8) Java中CyclicBarrier 和 CountDownLatch有什么不同?
CyclicBarrier 和 CountDownLatch 都可以用來讓一組線程等待其它線程。與 CyclicBarrier 不同的是,CountdownLatch 不能重新使用。
9) Java內(nèi)存模型是什么?
Java內(nèi)存模型規(guī)定和指引Java程序在不同的內(nèi)存架構(gòu)、CPU和操作系統(tǒng)間有確定性地行為。它在多線程的情況下尤其重要。Java內(nèi)存模型對一個線程所做的變動能被其它線程可見提供了**,它們之間是先行發(fā)生關(guān)系。這個關(guān)系定義了一些規(guī)則讓程序員在并發(fā)編程時思路更清晰。比如,先行發(fā)生關(guān)系確保了:
線程內(nèi)的代碼能夠按先后順序執(zhí)行,這被稱為程序次序規(guī)則。
對于同一個鎖,一個解鎖操作一定要發(fā)生在時間上后發(fā)生的另一個鎖定操作之前,也叫做管程鎖定規(guī)則。
前一個對volatile的寫操作在后一個volatile的讀操作之前,也叫volatile變量規(guī)則。
一個線程內(nèi)的任何操作必需在這個線程的start()調(diào)用之后,也叫作線程啟動規(guī)則。
一個線程的所有操作都會在線程終止之前,線程終止規(guī)則。
一個對象的終結(jié)操作必需在這個對象構(gòu)造完成之后,也叫對象終結(jié)規(guī)則。
可傳遞性
強(qiáng)烈建議大家閱讀《Java并發(fā)編程實踐》第十六章來加深對Java內(nèi)存模型的理解。
10) Java中的volatile 變量是什么?
volatile是一個特殊的修飾符,只有成員變量才能使用它。在Java并發(fā)程序缺少同步類的情況下,多線程對成員變量的操作對其它線程是透明的。volatile變量可以**下一個讀取操作會在前一個寫操作之后發(fā)生。線程都會直接從內(nèi)存中讀取該變量并且不緩存它。這就確保了線程讀取到的變量是同內(nèi)存中是一致的。
11) 什么是線程安全?Vector是一個線程安全類嗎?
如果你的代碼所在的進(jìn)程中有多個線程在同時運(yùn)行,而這些線程可能會同時運(yùn)行這段代碼。如果每次運(yùn)行結(jié)果和單線程運(yùn)行的結(jié)果是一樣的,而且其他的變量的值也和預(yù)期的是一樣的,就是線程安全的。一個線程安全的計數(shù)器類的同一個實例對象在被多個線程使用的情況下也不會出現(xiàn)計算失誤。很顯然你可以將集合類分成兩組,線程安全和非線程安全的。Vector 是用同步方法來實現(xiàn)線程安全的, 而和它相似的ArrayList不是線程安全的。
12) Java中什么是競態(tài)條件?
在大多數(shù)實際的多線程應(yīng)用中,兩個或兩個以上的線程需要共享對同一數(shù)據(jù)的存取。如果i線程存取相同的對象,并且每一個線程都調(diào)用了一個修改該對象狀態(tài)的方法,將會發(fā)生什么呢?可以想象,線程彼此踩了對方的腳。根據(jù)線程訪問數(shù)據(jù)的次序,可能會產(chǎn)生訛誤的對象。這樣的情況通常稱為競爭條件。