Java線程的一些面試題目

1.什麼是線程
    線程是操作系統能夠進行運算調度的最小單位,它被包含在進程當中,是進程的實際運作單位。
2.線程和進程的區別
    一個進程是一個獨立的運行環境,它可以被看做是一個程序或應用。線程是進程中執行的一個任務。線程是進程的子集,一個進程可以有多個線程。進程獨佔一片內存,進程共享內存。

3.CyclicBarrier和CountDownLatch有什麼不同
    CountDownLatch和CyclicBarrier都用於讓線程等待,達到一定條件時再運行。CountDownlatch更加靈活可以在一個線程中多次使用,但是不能重置計數器。CyclicBarrier更加強大,可以重置計數器reset(),可以檢查被阻塞的數目,可以檢查被阻塞的線程是否被中斷。
4.java內存模型是什麼(JMM java Memory Model)
    java內存模型規定和指引java程序在不同的內存架構,CPU,操作系統中有確定性的行爲。JMM定義了線程與主存之間的關係,JMM控制一個線程的共享變量的寫入何時對另一個線程可見。

5.happens-before原則
    程序順序規則:一個線程中的任意操作happens-before該線程中的任意後續操作
    監視器鎖原則:對於一個鎖的解鎖happens-before該鎖的加鎖。
    volatile變量原則:volatile寫happens-before volatile讀
    傳遞性原則:A happens-before B B happens-before C A happens-before C.
          A happens-before B 並不是 A比B先執行,而是A的執行結果對B可見。且 A按順序排在B之前

6.Java中的volatile變量是什麼
    Volatile是成員變量的修飾符,能夠保證該變量在多線程中的可見性。實現原理是將寫緩存刷新到主存中,然後根據緩存一致性原則保證可見性。
7.什麼是線程安全?Vector是一個安全類嗎
    在多線程中每一次讀的數據和預期數據一樣就是線程安全(此描述不夠準確)
8.如何實現兩個線程間共享數據
    1.通過類變量直接將數據放到主存中
    2.通過併發的數據結構來存儲數據
    3.使用volatile變量或者鎖
    4.調用atomic類
9.爲什麼wait(),notify(),notifyAll()在對象中,而不在Thread類中
    java中鎖的級別是對象級而不是線程級,每個對象都有鎖,通過線程獲得。如果wait()方法在線程中,線程正在等待的是哪個鎖就不明顯了。
10.什麼是ThreadLocal變量
    ThreadLocal變量是一種特殊的變量,它可以將變量保存副本ThreadLocalMap中供每個線程單獨使用。
    ThreadLocal 詳細解析
    1.ThreadLocal的結構
      成員變量: threadLocalHashCode   用來區分不同的ThreadLocal
      靜態內部類:ThreadLocalMap       用來存儲ThreadLocal
      方法set(): 通過獲取當前線程t,然後獲得一個threadlocalmap。第一次使用ThreadLocal時會初始化一個ThreadLocalMap,然後複製給當前線程。
11.什麼是futureTask
    RunnableFuture繼承了Runnable接口和Future接口。它可以取消和啓動一個線程的運行,當調用該類的線程未完成時調用get()會阻塞調用線程,當線程已經完成時會返回結果。futureTask的底層實現原理是AQS 
12.java中interrupt(),interrupted()和isInterrupted()的區別
    interrupt()是一個成員方法,調用時會改變中斷狀態,但是不會中斷線程,只有catch後會中斷線程。
    interrupted()是一個靜態方法,會中斷線程,中斷狀態爲true。
    isInterrupted()是一個成員方法,會中斷線程,中斷狀態爲false。
    
        public static boolean interrupted() {
            return currentThread().isInterrupted(true);
        }
    
        public boolean isInterrupted() {
            return this.isInterrupted(false);
        }
    private native boolean isInterrupted(boolean var1);
    上面是源碼,也就是說都調用的是本地方法,只是傳入的參數不一樣而已。
13.爲什麼wait和notify方法要在同步塊中調用?
    wait和notify都需要獲得對象鎖
14.爲什麼你應該在循環中檢查等待條件?
    代碼
    因爲處於等待的線程可能會被假喚醒和錯誤警報,如果不在循環中等待可能會因爲沒有滿足條件就退出等待。比如說,退出等待的條件是list()不爲空,有7個線程在等待。當list爲空時7個都將被喚醒,刪除元素會報錯。
15.同步集合和併發集合有什麼不一樣
    同步集合的鎖用的是sychronized,比較武斷。併發集合的鎖用的是AQS,靈活性更高,擴展性更強。
16. 有三個線程T1,T2,T3,怎麼確保它們按順序執行(確保main()方法所在的線程是Java程序最後結束的線程)?
    使用CountDownLatch()和ClclicBarrier方法都可以實現main()方法最後執行。在前一個線程調用後一個線程的join()方法可以按順序執行。
17.如果你提交任務時,線程池隊列已滿。會時發會生什麼?
    如果coreSize<maxSize 則會創建新的線程來執行任務。如果coreSize=MaxSize 會拋出一個RejectExecutionException.
18.你對線程優先級的理解是什麼?
    多線程其實是對CPU的輪詢執行,只是CPU處理的速度太快了感覺不到上下文的切換。優先級就是CPU輪詢線程的概率,優先級越高概率越高,優先級越低概率越低。
19.什麼是線程池
    線程池是管理多線程的一種工具,一個進程可以創建的線程數量是有限的,通過線程池創建的線程執行完成一個任務後不會立即關閉,而是繼續執行阻塞隊列中的線程直到阻塞線程爲空。
20.有那些阻塞隊列
    ArrayBlockingQueue       一個由數組構成的有界阻塞隊列
    LinkedBlockingQueue      一個由鏈表構成的有界阻塞隊列
    PriorityBlockingQueue    一個支持優先級排序的無界阻塞隊列
    DelayQueue               一個使用優先隊列實現的無界阻塞隊列。
    SynchroniouQueue         一個不儲存元素的阻塞隊列
    LinkedTransferQueue      一個由鏈表結構組成的無界阻塞隊列
    LinkedBlockingDeque      一個由鏈表結構組成的雙向阻塞隊列
21.Java中synchronized 和 ReentrantLock 有什麼不同?
    synchronized是一個隱式的重入鎖,比較笨重,實現方式是鎖主存和緩存一致性。
    reentrantLock是一個顯示的重入鎖,比較靈活,可以擴展爲分段鎖,實現方式是AQS.
22.如何避免死鎖?
    死鎖發生的條件是
    1.存在循環等待
    2.存在資源競爭
    3.不剝奪條件,已經獲得的資源不會被剝奪
    4.請求與保持,一個線程因請求資源被阻塞時,擁有資源的線程的狀態不會改變。
    避免死鎖只需要破環其中的一個條件就可以了。
23. 怎麼檢測一個線程是否擁有鎖?
    Thread中有一個holdLock()方法,當且僅當當前線程擁有某個具體的對象鎖時返回true
24.JVM中哪個參數是用來控制線程的棧堆棧小的
    -Xss    
25. Thread類中的yield方法有什麼作用?
    它會會通知cpu在此處可以更換切片,更不更換由cpu自己決定。(yield可以暫停當前正在執行的線程對象,讓其他有線程執行)
26.Java中ConcurrentHashMap的併發度是什麼?
    併發度就是segment的個數,通常是2的N次方。默認是16
27.java中的Semaphore是什麼
    它是一個新的同步類,是一個計數信號。比如在數據庫連接池中,假設我們只能獲得10個數據庫連接,20大小的線程池。此時我們就可以用一個Semaphore來表示數據庫連接池的數目,當需要使用時就accquire()取得許可,使用完畢就release()添加一個許可。
28. 什麼是線程調度器(Thread Scheduler)和時間分片(Time Slicing)?
    線程調度器是一種操作系統服務,它負責給線程任務分配CPU處理的時間。時間分片指的是CPU一次性處理的一個任務的片段,分配CPU時間可以基於線程優先級或者線程等待時間,但是線程調度並不收到JVM的控制。
29.在多線程中,什麼是上下文切換(context-switching)?
    上線文切換是指CPU存儲和恢復狀態的過程,它使得線程能夠從中斷狀態恢復繼續運行。
30.如何在Java中創建Immutable對象?
    將類和成員變量都設置爲final,且成員爲私有,成員的初始化通過構造參數初始化。不提供setter()方法。immutable的好處是在沒有同步的情況下是線程安全的。
31. Java中的ReadWriteLock是什麼?
    它的名稱是讀寫鎖,實現原理是AQS.它將32位的 state狀態變量分爲前16位和後16位,前16位狀態表示爲讀的狀態,後16位狀態表示爲寫的狀態。也就是說讀寫鎖有兩把鎖,一把控制讀,一把控制寫。寫鎖和寫鎖互斥,寫鎖和讀鎖互斥,讀鎖和互鎖相容,寫鎖可以降級爲讀鎖。
32.多線程中的忙循環是什麼?
    忙循環是指程序員用循環來代替wait()方法讓線程進入等待,它的好處是可以佔用CPU,不放棄緩存可以減少將數據讀入緩存的時間。
33.volatile 變量和 atomic 變量有什麼不同?
    volatile的實現方式是將緩存中的值刷新到主存中,本生具有可見性和原子性但是volatile++不具有原子性。
    atomic的實現方式是CAS.本質有點類似,也是緩存一致性原則。
34.單例模式的雙檢鎖是什麼?
    當實例爲空時,加鎖再判斷是否爲空。如果爲空則創建一個新的實例。
    安全嗎?不安全
    原因:在創建一個對象的時候會分爲三個步驟   1.爲對象分配內存    2.在內存中初始化一個對象  3.將對象指配給使用者。步驟2依賴於1,所以不會被重排序。步驟3和步驟2沒有依賴可能會被重排序。所以當另外一個線程在此時調用單例可能會獲得一個空的實例。
35.如何在java中創建線程安全的Singleton
    1.先加鎖,再判斷。
    2.用一個volatile變量進行標識。
    3.反射
36. 寫出3條你遵循的多線程最佳實踐
    多用同步類,少用wait,notify
    少用鎖,應當縮小同步範圍
    給線程一個自己的名字
    多用併發集合少用同步集合
37.如何強制啓動一個線程?
    我覺得沒有方法強制啓動,就像垃圾回收一樣,即使調用了System.gc也不會馬上就gc。因爲java中的一個線程和操作系統中的一個線程是一一對應的。操作系統的線程什麼時候在cpu上輪詢由操作系統決定,jvm沒有權限就像優先級一樣。
38.java中的fork/join框架是什麼
    它是jdk7中的一款高效併發編程工具,它利用工作竊取算法將一個大任務劃分爲若干個子任務,然後將子任務結果合併起來,從而提高了併發編程的效率。
39.線程調度策略?
    1.搶佔式調度策略
      處於就緒態的線程,根據優先級搶佔進入運行態。
    2.時間片輪轉調度策略
      所有處於就緒狀態的線程中選擇優先級最高的線程分配一定的CPU時間運行,該時間過後再選擇其他線程運行。
40.在線程中你怎麼處理不可捕捉異常?
    hread.UncaughtExceptionHandler是java SE5中的新接口,它允許我們在每一個Thread對象上添加一個異常處理器。

41.synchronized的三種應用方式

Java中每一個對象都可以作爲鎖,這是synchronized實現同步的基礎:

普通同步方法(實例方法),鎖是當前實例對象 ,進入同步代碼前要獲得當前實例的鎖
靜態同步方法,鎖是當前類的class對象 ,進入同步代碼前要獲得當前類對象的鎖
同步方法塊,鎖是括號裏面的對象,對給定對象加鎖,進入同步代碼庫前要獲得給定對象的鎖。

 

又要開始找工作了,先準備點面試題目.後面會繼續更新
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章