Java程式設計師面試中的多線程問題

  很多核心Java面試題來源於多線程(Multi-Threading)和集合框架(Collections
Framework),理解核心線程概念時,嫻熟的實際經驗是必需的。這篇文章收集了 Java 線程方面一些典型的問題,這些問題經常被高級工程師所問到。

  0.Java 中多線程同步是什麼?

  在多線程程序下,同步能控制對共享資源的訪問。如果沒有同步,當一個 Java
線程在修改一個共享變量時,另外一個線程正在使用或者更新同一個變量,這樣容易導致程序出現錯誤的結果。

  1.解釋實現多線程的幾種方法?

  一 Java 線程可以實現 Runnable 接口或者繼承 Thread 類來實現,當你打算多重繼承時,優先選擇實現 Runnable。

  2.Thread.start ()與 Thread.run ()有什麼區別?

  Thread.start ()方法(native)啟動線程,使之進入就緒狀態,當 cpu 分配時間該線程時,由 JVM 調度執行 run
()方法。

  3.為什麼需要 run ()和 start ()方法,我們可以只用 run ()方法來完成任務嗎?

  我們需要 run ()&start ()這兩個方法是因為 JVM 創建一個單獨的線程不同於普通方法的調用,所以這項工作由線程的 start
方法來完成,start 由本地方法實現,需要顯示地被調用,使用這倆個方法的另外一個好處是任何一個對象都可以作為線程運行,只要實現了 Runnable
接口,這就避免因繼承了 Thread 類而造成的 Java 的多繼承問題。

  4.什麼是 ThreadLocal 類,怎麼使用它?

  ThreadLocal 是一個線程級別的局部變量,並非「本地線程」。ThreadLocal
為每個使用該變量的線程提供了一個獨立的變量副本,每個線程修改副本時不影響其它線程對象的副本(譯者注)。

  下面是線程局部變量(ThreadLocal variables)的關鍵點:

  一個線程局部變量(ThreadLocal variables)為每個線程方便地提供了一個單獨的變量。

  ThreadLocal 實例通常作為靜態的私有的(private static)欄位出現在一個類中,這個類用來關聯一個線程。

  當多個線程訪問 ThreadLocal 實例時,每個線程維護 ThreadLocal 提供的獨立的變量副本。

  常用的使用可在 DAO 模式中見到,當 DAO
類作為一個單例類時,資料庫連結(connection)被每一個線程獨立的維護,互不影響。(基於線程的單例)

  ThreadLocal 難於理解,下面這些引用連接有助於你更好的理解它。

  《Good article on ThreadLocal on IBM DeveloperWorks 》、《理解
ThreadLocal》、《Managing data : Good example》、《Refer Java API Docs》

  5.什麼時候拋出 InvalidMonitorStateException 異常,為什麼?

  調用 wait ()/notify ()/notifyAll ()中的任何一個方法時,如果當前線程沒有獲得該對象的鎖,那麼就會拋出
IllegalMonitorStateException 的異常(也就是說程序在沒有執行對象的任何同步塊或者同步方法時,仍然嘗試調用 wait
()/notify ()/notifyAll ()時)。由於該異常是 RuntimeExcpetion
的子類,所以該異常不一定要捕獲(儘管你可以捕獲只要你願意).作為 RuntimeException,此類異常不會在 wait (),notify
(),notifyAll ()的方法簽名提及。

  6.Sleep ()、suspend ()和 wait ()之間有什麼區別?

  Thread.sleep ()使當前線程在指定的時間處於「非運行」(Not
Runnable)狀態。線程一直持有對象的監視器。比如一個線程當前在一個同步塊或同步方法中,其它線程不能進入該塊或方法中。如果另一線程調用了 interrupt
()方法,它將喚醒那個「睡眠的」線程。

  注意:sleep ()是一個靜態方法。這意味著只對當前線程有效,一個常見的錯誤是調用t.sleep
(),(這裡的t是一個不同於當前線程的線程)。即便是執行t.sleep (),也是當前線程進入睡眠,而不是t線程。t.suspend ()是過時的方法,使用
suspend ()導致線程進入停滯狀態,該線程會一直持有對象的監視器,suspend ()容易引起死鎖問題。

  object.wait ()使當前線程出於「不可運行」狀態,和 sleep ()不同的是 wait 是 object 的方法而不是 thread。調用
object.wait ()時,線程先要獲取這個對象的對象鎖,當前線程必須在鎖對象保持同步,把當前線程添加到等待隊列中,隨後另一線程可以同步同一個對象鎖來調用
object.notify (),這樣將喚醒原來等待中的線程,然後釋放該鎖。基本上 wait ()/notify ()與 sleep ()/interrupt
()類似,只是前者需要獲取對象鎖。

  7.在靜態方法上使用同步時會發生什麼事?

  同步靜態方法時會獲取該類的「Class」對象,所以當一個線程進入同步的靜態方法中時,線程監視器獲取類本身的對象鎖,其它線程不能進入這個類的任何靜態同步方法。它不像實例方法,因為多個線程可以同時訪問不同實例同步實例方法。

  8.當一個同步方法已經執行,線程能夠調用對象上的非同步實例方法嗎?

  可以,一個非同步方法總是可以被調用而不會有任何問題。實際上,Java
沒有為非同步方法做任何檢查,鎖對象僅僅在同步方法或者同步代碼塊中檢查。如果一個方法沒有聲明為同步,即使你在使用共享數據 Java
照樣會調用,而不會做檢查是否安全,所以在這種情況下要特別小心。一個方法是否聲明為同步取決於臨界區訪問(critial section
access),如果方法不訪問臨界區(共享資源或者數據結構)就沒必要聲明為同步的。

  下面有一個示例說明:Common 類有兩個方法 synchronizedMethod1()和 method1(),MyThread
類在獨立的線程中調用這兩個方法。

  public class Common { public synchronized void synchronizedMethod1() {
System.out.println ("synchronizedMethod1 called"); try { Thread.sleep (1000); }
catch (InterruptedException e) { e.printStackTrace (); } System.out.println
("synchronizedMethod1 done"); } public void method1() { System.out.println
("Method 1 called"); try { Thread.sleep (1000); } catch (InterruptedException e)
{ e.printStackTrace (); } System.out.println ("Method 1 done"); } }

  public class MyThread extends Thread { private int id = 0; private Common
common; public MyThread (String name, int no, Common object) { super(name);
common = object; id = no; } public void run () { System.out.println ("Running
Thread" + this.getName ()); try { if (id == 0) { common.synchronizedMethod1(); }
else { common.method1(); } } catch (Exception e) { e.printStackTrace (); } }
public static void main (String[] args) { Common c = new Common (); MyThread t1
= new MyThread ("MyThread-1", 0, c); MyThread t2 = new MyThread ("MyThread-2",
1, c); t1.start (); t2.start (); } }

  這裡是程序的輸出:

  Running ThreadMyThread-1 synchronizedMethod1 called Running
ThreadMyThread-2 Method 1 called synchronizedMethod1 done Method 1 done

  結果表明即使 synchronizedMethod1()方法執行了,method1()也會被調用。

  9.在一個對象上兩個線程可以調用兩個不同的同步實例方法嗎?

  不能,因為一個對象已經同步了實例方法,線程獲取了對象的對象鎖。所以只有執行完該方法釋放對象鎖後才能執行其它同步方法。看下面代碼示例非常清晰:Common
類有 synchronizedMethod1()和 synchronizedMethod2()方法,MyThread 調用這兩個方法。

  public class Common { public synchronized void synchronizedMethod1() {
System.out.println ("synchronizedMethod1 called"); try { Thread.sleep (1000); }
catch (InterruptedException e) { e.printStackTrace (); } System.out.println
("synchronizedMethod1 done"); } public synchronized void synchronizedMethod2() {
System.out.println ("synchronizedMethod2 called"); try { Thread.sleep (1000); }
catch (InterruptedException e) { e.printStackTrace (); } System.out.println
("synchronizedMethod2 done"); } }

  public class MyThread extends Thread { private int id = 0; private Common
common; public MyThread (String name, int no, Common object) { super(name);
common = object; id = no; } public void run () { System.out.println ("Running
Thread" + this.getName ()); try { if (id == 0) { common.synchronizedMethod1(); }
else { common.synchronizedMethod2(); } } catch (Exception e) { e.printStackTrace
(); } } public static void main (String[] args) { Common c = new Common ();
MyThread t1 = new MyThread ("MyThread-1", 0, c); MyThread t2 = new MyThread
("MyThread-2", 1, c); t1.start (); t2.start (); } }

  10.什麼是死鎖

  死鎖就是兩個或兩個以上的線程被無限的阻塞,線程之間相互等待所需資源。這種情況可能發生在當兩個線程嘗試獲取其它資源的鎖,而每個線程又陷入無限等待其它資源鎖的釋放,除非一個用戶進程被終止。就
JavaAPI 而言,線程死鎖可能發生在一下情況。

  當兩個線程相互調用 Thread.join ()

  當兩個線程使用嵌套的同步塊,一個線程占用了另外一個線程必需的鎖,互相等待時被阻塞就有可能出現死鎖。

  11.什麼是線程餓死,什麼是活鎖?

  線程餓死和活鎖雖然不想是死鎖一樣的常見問題,但是對於並發編程的設計者來說就像一次邂逅一樣。

  當所有線程阻塞,或者由於需要的資源無效而不能處理,不存在非阻塞線程使資源可用。JavaAPI 中線程活鎖可能發生在以下情形:

  當所有線程在程序中執行 Object.wait (0),參數為 0 的 wait 方法。程序將發生活鎖直到在相應的對象上有線程調用
Object.notify ()或者 Object.notifyAll ()。

  當所有線程卡在無限循環中。

  這裡的問題並不詳盡,我相信還有很多重要的問題並未提及,您認為還有哪些問題應該包括在上面呢?歡迎在評論中分享任何形式的問題與建議

相關文章

  1. java程式設計師面試交流項目經驗

    1:請你介紹一下你自己這是面試官常問的問題.一般人回答這個問題過於平常,只說姓名.愛好.工作經驗,這些簡歷上都有.其實,面試官最希望知道的是求職者能否勝任工作,包括:最強的技能.最深入研究的知識領域. ...
  2. 淺談關於java程式設計師面試的一些事項

    簡單的說一下筆試,筆試這個環節是很容易通過的,無非就是幾張試卷,一共也就十幾道題.一般由5至10個選擇題+2至5個論述題+1至2個編程題 組成. 接過筆試題之後,第一步要平靜心態,第二步要瀏覽所有題目 ...
  3. java程式設計師面試----交流項目經驗

    1:請你介紹一下你自己這是面試官常問的問題. 2:說說你的家庭面試時詢問家庭問題不是非要知道求職者家庭情況,探究隱私,而是要了解家庭背景對求職者的塑造和影響.面試官希望聽到的重點也在於家庭對求職者的積 ...
  4. Java程式設計師面試問題以及答案

    面試的時候我們經常會被問一些常用的java提知識和一些個人問題,弄得我們不知所錯,本人是一面hr後來學習了java現在是一名三年經驗的程式設計師,幫助了很多學生就業希望我的經驗能夠幫助你們找的答案和自信. ...
  5. java程式設計師面試如何談薪資?程式設計師面試談薪技巧

    在當前網際網路發展前景越來越好的情況,加上目前市場上專業程式設計師稀缺,也就導致Java程式設計師薪資水漲船高.那麼,談及薪水就不得不考慮到程式設計師在面試的時候,該如何更好的向企業談薪這個問題?就讓千鋒廣州Jav ...
  6. Java程式設計師要掌握的十個JSP中的標籤庫

    Standard 這個庫必不可少,因為它結合了對普通JSP的大量核心改進.它的一些特性包括:XML操作庫.SQL庫.特殊國際化功能.以及對疊代器和其它程序控制機制的支持.在需要高級流程控制結構.國際化 ...
  7. JAVA程式設計師如何找工作面試

                                         JAVA程式設計師找工作面試  很多java程式設計師在面試的時候成功率很低,在找工作的時候也是比較害怕面試和筆試, 如何有技巧的應對 ...
  8. Java程式設計師必須知道的5個調試技巧

    試可以幫助識別和解決應用程式缺陷,在本文中,作者將使用大家常用的的開發工具Eclipse來調試Java應用程式.但這裡介紹的調試方法基本都是通用的,也適用於NetBeans IDE,我們會把重點放在運 ...
  9. 什麼是程式設計師面試最重要的因素

    程式設計師面試一直是社區樂於討論的熱門話題.我自己從06年實習以來,先後經歷了4家軟體公司,全部是外企,其中有世界500強的通信企業,有從事期權期貨交易的歐洲中等規模的金融公司,也有為大型汽車製造商開發A ...
  10. Java程式設計師應該避免犯的21種錯誤

    1.Duplicated Code 代碼重複幾乎是最常見的異味了.他也是Refactoring的主要目標之一.代碼重複往往來自於copy-and-paste的編程風格.與他相對應OAOO是一個好系統的 ...
  11. 一個java程式設計師必備的9項基本技能

    目前,JAVA是開發人員的熱寵,別以為你學過Java培訓,就是個合格的程式設計師,其實你還有很多不懂的,看看下面的這些技能你都會嗎? 1.語法: 必須比較熟悉,在寫代碼的時候IDE的編輯器對某一行報錯應該 ...
  12. Java程式設計師的筆試題10道

    1.HashMap和Hashtable的區別. 都屬於Map接口的類,實現了將惟一鍵映射到特定的值上.HashMap 類沒有分類或者排序.它允許一個null 鍵和多個null 值.Hashtable ...
  13. java程式設計師的學習方法

    有很多的JAVA程式設計師,在初期學習時,通常會對如何學習而感到迷茫.下面筆者就將轉發一篇一位網友的精品帖,這位作者對於JAVA程序的學習分析的很到位,相信能幫助那些正在處於迷茫狀態的初學者. 如何學習程 ...
  14. 程式設計師面試時應注意的幾個細節

    都說"十年寒窗苦,一舉成名天下知",這是自古以來,我們學習的目標與動力,隨著時代的變化,現在,我們學習的目標與動力更多的是為了更好的工作,更好的薪資報酬.經過漫長的學習過程,我們學 ...
  15. java程式設計師要學的c語法

    (1)函數原型:extern char strstr(char *haystack,char *needle); 用法:#include<string.h> 功能:從字符串haystack ...
  16. 程式設計師面試技巧

    我們也發現,很多很多有才華的程式設計師都在面試的時候總是掉鏈子,這大概是因為他們把大多數的時間都用來搞開發技術,而忽略了學習面試技巧的重要性. 工具/原料 專業技能以及熱情 方法/步驟 給自己寫一份非常專 ...
  17. java軟體開發人員面試準備

    每年的3-4月都是軟體公司的招聘季,也是軟體開發人員的跳槽月,最近面試了幾家軟體公司,說說自己的心得,希望能幫助正在面試的同學,本篇經驗適用於有工作經驗的開發人員. 方法/步驟 準備好3分鐘的自我介紹 ...
  18. 程式設計師面試的一些技巧

    有才華的程式設計師在面試的時候總是掉鏈子,這大概是因為他們把大多數時間都用來搞技術開發,而忽略了學習面試技巧的重要性.下面講述程式設計師面試的一些技巧. 方法/步驟 結合自己實際情況,寫一份非常專業的簡歷.面 ...
  19. 程式設計師面試的幾個細節

    都說"十年寒窗苦,一舉成名天下知",這是自古以來,我們學習的目標與動力,隨著時代的變化,現在,我們學習的目標與動力更多的是為了更好的工作,更好的薪資報酬.經過漫長的學習過程,我們學 ...
  20. Java程式設計師找工作方法(應屆生)

    1.選擇方向(Java工程師). 明確自己的方向,是C++,還是C#,還是Java. 2.複習指南. 看<劍指Offer>. 3.製作簡歷. 在網上買一些好的簡歷模板. 4.簡歷投遞方法. ...