Java程序員面試題集錦

Java面試隨着時間的改變而改變。在過去的日子裏,當你知道String和StringBuilder的區別就能讓你直接進入第二輪面試,但是現在問題變得越來越高級,面試官問的問題也更深入。下面是小編整理的關於Java程序員面試題集錦,希望大家認真閱讀!

Java程序員面試題集錦

1)Java中能創建Volatile數組嗎?

能,Java中可以創建volatile類型數組,不過只是一個指向數組的引用,而不是整個數組。我的意思是,如果改變引用指向的數組,將會受到volatile的保護,但是如果多個線程同時改變數組的元素,volatile標示符就不能起到之前的保護作用了。

2)volatile能使得一個非原子操作變成原子操作嗎?

一個典型的例子是在類中有一個long類型的成員變量。如果你知道該成員變量會被多個線程訪問,如計數器、價格等,你最好是將其設置爲volatile。爲什麼?因爲Java中讀取long類型變量不是原子的,需要分成兩步,如果一個線程正在修改該long變量的值,另一個線程可能只能看到該值的一半(前32位)。但是對一個volatile型的long或double變量的讀寫是原子。

3)volatile修飾符的有過什麼實踐?

一種實踐是用volatile修飾long和double變量,使其能按原子類型來讀寫。double和long都是64位寬,因此對這兩種類型的讀是分爲兩部分的,第一次讀取第一個32位,然後再讀剩下的32位,這個過程不是原子的,但Java中volatile型的long或double變量的讀寫是原子的。volatile修復符的另一個作用是提供內存屏障(memorybarrier),例如在分佈式框架中的應用。簡單的說,就是當你寫一個volatile變量之前,Java內存模型會插入一個寫屏障(writebarrier),讀一個volatile變量之前,會插入一個讀屏障(readbarrier)。意思就是說,在你寫一個volatile域時,能保證任何線程都能看到你寫的值,同時,在寫之前,也能保證任何數值的更新對所有線程是可見的,因爲內存屏障會將其他所有寫的值更新到緩存。

4)volatile類型變量提供什麼保證?(答案)

volatile變量提供順序和可見性保證,例如,JVM或者JIT爲了獲得更好的性能會對語句重排序,但是volatile類型變量即使在沒有同步塊的情況下賦值也不會與其他語句重排序。volatile提供happens-before的保證,確保一個線程的修改能對其他線程是可見的。某些情況下,volatile還能提供原子性,如讀64位數據類型,像long和double都不是原子的,但volatile類型的double和long就是原子的。

5)10個線程和2個線程的同步代碼,哪個更容易寫?

從寫代碼的角度來說,兩者的複雜度是相同的,因爲同步代碼與線程數量是相互獨立的。但是同步策略的選擇依賴於線程的數量,因爲越多的線程意味着更大的競爭,所以你需要利用同步技術,如鎖分離,這要求更復雜的代碼和專業知識。

6)你是如何調用wait()方法的?使用if塊還是循環?爲什麼?(答案)

wait()方法應該在循環調用,因爲當線程獲取到CPU開始執行的時候,其他條件可能還沒有滿足,所以在處理前,循環檢測條件是否滿足會更好。下面是一段標準的使用wait和notify方法的代碼://Thestandardidiomforusingthewaitmethod

參見EffectiveJava第69條,獲取更多關於爲什麼應該在循環中來調用wait方法的內容。

7)Java中應該使用什麼數據類型來代表價格?(答案)

如果不是特別關心內存和性能的話,使用BigDecimal,否則使用預定義精度的double類型。

8)什麼是Busyspin?我們爲什麼要使用它?

Busyspin是一種在不釋放CPU的基礎上等待事件的技術。它經常用於避免丟失CPU緩存中的數據(如果線程先暫停,之後在其他CPU上運行就會丟失)。所以,如果你的工作要求低延遲,並且你的線程目前沒有任何順序,這樣你就可以通過循環檢測隊列中的新消息來代替調用sleep()或wait()方法。它唯一的好處就是你只需等待很短的`時間,如幾微秒或幾納秒。LMAX分佈式框架是一個高性能線程間通信的庫,該庫有一個BusySpinWaitStrategy類就是基於這個概念實現的,使用busyspin循環EventProcessors等待屏障。

9)Java中怎麼獲取一份線程dump文件?

在Linux下,你可以通過命令kill-3PID(Java進程的進程ID)來獲取Java應用的dump文件。在Windows下,你可以按下Ctrl+Break來獲取。這樣JVM就會將線程的dump文件打印到標準輸出或錯誤文件中,它可能打印在控制檯或者日誌文件中,具體位置依賴應用的配置。如果你使用Tomcat。

10)Swing是線程安全的?(答案)

不是,Swing不是線程安全的。你不能通過任何線程來更新Swing組件,如JTable、JList或JPanel,事實上,它們只能通過GUI或AWT線程來更新。這就是爲什麼Swing提供invokeAndWait()和invokeLater()方法來獲取其他線程的GUI更新請求。這些方法將更新請求放入AWT的線程隊列中,可以一直等待,也可以通過異步更新直接返回結果。你也可以在參考答案中查看和學習到更詳細的內容。

11)什麼是線程局部變量?(答案)

線程局部變量是侷限於線程內部的變量,屬於線程自身所有,不在多個線程間共享。Java提供ThreadLocal類來支持線程局部變量,是一種實現線程安全的方式。但是在管理環境下(如web服務器)使用線程局部變量的時候要特別小心,在這種情況下,工作線程的生命週期比任何應用變量的生命週期都要長。任何線程局部變量一旦在工作完成後沒有釋放,Java應用就存在內存泄露的風險。

12)用wait-notify寫一段代碼來解決生產者-消費者問題?(答案)

請參考答案中的示例代碼。只要記住在同步塊中調用wait()和notify()方法,如果阻塞,通過循環來測試等待條件。

13)用Java寫一個線程安全的單例模式(Singleton)?(答案)

請參考答案中的示例代碼,這裏面一步一步教你創建一個線程安全的Java單例類。當我們說線程安全時,意思是即使初始化是在多線程環境中,仍然能保證單個實例。Java中,使用枚舉作爲單例類是最簡單的方式來創建線程安全單例模式的方式。

14)Java中sleep方法和wait方法的區別?(答案)

雖然兩者都是用來暫停當前運行的線程,但是sleep()實際上只是短暫停頓,因爲它不會釋放鎖,而wait()意味着條件等待,這就是爲什麼該方法要釋放鎖,因爲只有這樣,其他等待的線程才能在滿足條件時獲取到該鎖。

15)什麼是不可變對象(immutableobject)?Java中怎麼創建一個不可變對象?(答案)

不可變對象指對象一旦被創建,狀態就不能再改變。任何修改都會創建一個新的對象,如String、Integer及其它包裝類。詳情參見答案,一步一步指導你在Java中創建一個不可變的類。