1. 線程同步以及線程調(diào)度相關的方法
- wait():使一個線程處于等待(阻塞)狀態(tài),并且釋放所持有的對象的鎖;
- sleep():使一個正在運行的線程處于睡眠狀態(tài),是一個靜態(tài)方法,調(diào)用此方法要處理InterruptedException異常;
- notify():喚醒一個處于等待狀態(tài)的線程,當然在調(diào)用此方法的時候,并不能確切的喚醒某一個等待狀態(tài)的線程,而是由JVM確定喚醒哪個線程,而且與優(yōu)先級無關;
- notityAll():喚醒所有處于等待狀態(tài)的線程,該方法并不是將對象的鎖給所有線程,而是讓它們競爭,只有獲得鎖的線程才能進入就緒狀態(tài);
2. 進程和線程的區(qū)別
進程是執(zhí)行著的應用程序,而線程是進程內(nèi)部的一個執(zhí)行序列。一個進程可以有多個線程。
另一種回答:
線程是進程的一個單元,也是進程內(nèi)的可調(diào)度實體。區(qū)別就是:1、進程內(nèi)的線程共享地址空間,進程則自己獨立的地址空間。2、進程是資源分配和擁有的單位,同一個進程內(nèi)的線程共享進程資源。3、線程是處理器調(diào)度的基本單位。4、兩者均可并發(fā)執(zhí)行。
3. 實現(xiàn)線程有哪幾種方式?啟動線程調(diào)用什么方法?
Java中實現(xiàn)線程有兩種方式:第一種是繼承Thread,第二種是實現(xiàn)Runnable接口。啟動線程用start()方法。
4. 請說出你所知道的線程同步的方法。
wait():使一個線程處于等待狀態(tài),并且釋放所持有的對象的lock。
sleep():使一個正在運行的線程處于睡眠狀態(tài),是一個靜態(tài)方法,調(diào)用此方法要捕捉InterruptedException異常。
notify():喚醒一個處于等待狀態(tài)的線程,注意的是在調(diào)用此方法的時候,并不能確切的喚醒某一個等待狀態(tài)的線程,而是由JVM確定喚醒哪個線程,而且不是按優(yōu)先級。
notityAll():喚醒所有處入等待狀態(tài)的線程,注意并不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。
5. sleep() 和wait() 有什么區(qū)別?
sleep是線程類(Thread)的方法,導致此線程暫停執(zhí)行指定時間,把執(zhí)行機會給其他線程,但是監(jiān)控狀態(tài)依然保持,到時后會自動恢復。調(diào)用sleep不會釋放對象鎖。
? ? wait是Object類的方法,對此對象調(diào)用wait方法導致本線程放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象發(fā)出notify方法(或notifyAll)后本線程才進入對象鎖定池準備獲得對象鎖進入運行狀態(tài)。
6. 創(chuàng)建線程有幾種方式
創(chuàng)建線程有以下幾種方式:
? 繼承Thread類
? 實現(xiàn)Runnable接口
? 應用程序可以使用Executor框架來創(chuàng)建線程池
實現(xiàn)Runnable接口這種方式更受歡迎,因為這不需要繼承Thread類。在已經(jīng)繼承了別的類的情況下,這需要多繼承(而Java不支持多繼承),只能實現(xiàn)接口。同時,線程池也是非常高效的,很容易實現(xiàn)和使用。
7. synchronized關鍵字的用法,優(yōu)缺點
答:java關鍵字,當它用來修飾一個方法或者代碼塊的時候,能夠保證在同一時刻最多只有一個線程執(zhí)行該代碼段的代碼;
synchronized修飾的方法或者對象,只能以同步的方式執(zhí)行,會引起性能問題;無法中斷一個正在等候獲得鎖的線程,也無法通過投票獲得鎖;一個優(yōu)先級高的線程等待一個優(yōu)先級低的線程釋放鎖會導致優(yōu)先級倒置,引起性能風險;
8. Thread 類中的start() 和 run() 方法有什么區(qū)別?
start()方法被用來啟動新創(chuàng)建的線程,而且start()內(nèi)部 調(diào)用了run()方法,這和直接調(diào)用run()方法的效果不一樣。當你調(diào)用run()方法的時候,只會是在原來的線程中調(diào)用,沒有新的線程啟 動,start()方法才會啟動新線程。
9. Java中的volatile 變量是什么?
volatile是一個特殊的修飾符,只有成員變量才能使用它。在Java并發(fā)程序缺少同步類的情況下,多線程對成員變量的操作對其它線程是透明的。volatile變量可以保證下一個讀取操作會在前一個寫操作之后發(fā)生,就是上一題的volatile變量規(guī)則。
10. Java中notify 和 notifyAll有什么區(qū)別?
這又是一個刁鉆的問題,因為多線程可以等待單監(jiān)控鎖,Java API 的設計人員提供了一些方法當?shù)却龡l件改變的時候通知它們,但是這些方法沒有完全實現(xiàn)。notify()方法不能喚醒某個具體的線程,所以只有一個線程在等 待的時候它才有用武之地。而notifyAll()喚醒所有線程并允許他們爭奪鎖確保了至少有一個線程能繼續(xù)運行。
11. 為什么wait, notify 和 notifyAll這些方法不在thread類里面?
JAVA提供的鎖是對象級的而不是線程級的,每個對象都有鎖,通 過線程獲得。如果線程需要等待某些鎖那么調(diào)用對象中的wait()方法就有意義了。如果wait()方法定義在Thread類中,線程正在等待的是哪個鎖 就不明顯了。簡單的說,
由于wait,notify和notifyAll都是鎖級別的操作,所以把他們定義在Object類中因為鎖屬于對象。
12. 為什么wait和notify方法要在同步塊中調(diào)用?
主要是因為Java API強制要求這樣做,如果你不這么做,你的代碼會拋出IllegalMonitorStateException異常。還有一個原因是為了避免wait和notify之間產(chǎn)生競態(tài)條件。
13. Java中的同步集合與并發(fā)集合有什么區(qū)別?
同步集合與并發(fā)集合都為多線程和并發(fā)提供了合適的線程安全的集合,不過并發(fā)集合的可擴展性更高。在Java1.5之前程序員們只有同步集合來用且在 多線程并發(fā)的時候會導致爭用,阻礙了系統(tǒng)的擴展性。Java5介紹了并發(fā)集合像ConcurrentHashMap,不僅提供線程安全還用鎖分離和內(nèi)部分 區(qū)等現(xiàn)代技術提高了可擴展性。
14. Java中堆和棧有什么不同?
棧是一種線形集合,其添加和刪除元素的操作應在同一段完成。棧按照后進先出的方式進行處理。
堆是棧的一個組成元素
15. 什么是線程池? 為什么要使用它?
創(chuàng)建線程要花費昂貴的資源和時間,如果任務來了才創(chuàng)建線程那么響應時間會變長,而且一個進程能創(chuàng)建的線程數(shù)有限。為了避免這些問題,在程序啟動的時 候就創(chuàng)建若干線程來響應處理,它們被稱為線程池,里面的線程叫工作線程。從JDK1.5開始,Java API提供了Executor框架讓你可以創(chuàng)建不同的線程池。比如單線程池,每次處理一個任務;數(shù)目固定的線程池或者是緩存線程池(一個適合很多生存期短 的任務的程序的可擴展線程池)。
16. Java多線程中調(diào)用wait() 和 sleep()方法有什么不同?
Java程序中wait 和 sleep都會造成某種形式的暫停,它們可以滿足不同的需要。wait()方法用于線程間通信,如果等待條件為真且其它線程被喚醒時它會釋放鎖,而 sleep()方法僅僅釋放CPU資源或者讓當前線程停止執(zhí)行一段時間,但不會釋放鎖。
17. 同步方法和同步代碼塊的區(qū)別是什么?
同步方法就是在方法前加關鍵字synchronized,然后被同步的方法一次只能有一個線程進入,其他線程等待。
而同步代碼塊則是在方法內(nèi)部使用大括號使得一個代碼塊得到同步。同步塊會有一個鎖定的“對象”。同步代碼塊的同步范圍更加準確。
18. 同步和異步有何異同,在什么情況下分別使用他們?舉例說明。
如果數(shù)據(jù)將在線程間共享。例如正在寫的數(shù)據(jù)以后可能被另一個線程讀到,或者正在讀的數(shù)據(jù)可能已經(jīng)被另一個線程寫過了,那么這些數(shù)據(jù)就是共享數(shù)據(jù),必須進行同步存取。
當應用程序在對象上調(diào)用了一個需要花費很長時間來執(zhí)行的方法,并且不希望讓程序等待方法的返回時,就應該使用異步編程,在很多情況下采用異步途徑往往更有效率。
19. 什么是Java優(yōu)先級隊列(Priority Queue)?
PriorityQueue是一個基于優(yōu)先級堆的無界隊列,它的元素是按照自然順序(natural order)排序的。在創(chuàng)建的時候,我們可以給它提供一個負責給元素排序的比較器。PriorityQueue不允許null值,因為他們沒有自然順序,或者說他們沒有任何的相關聯(lián)的比較器。最后,PriorityQueue不是線程安全的,入隊和出隊的時間復雜度是O(log(n))。
20. 什么是同步?
同步用來控制共享資源在多個線程間的訪問,以保證同一時間內(nèi)只有一個線程能訪問到這個資源。在非同步保護的多線程程序里面,一個線程正在修改一個共享變量的時候,可能有另一個線程也在使用或者更新它的值。同步避免了臟數(shù)據(jù)的產(chǎn)生。