ゞ沉默是金ゞ

          魚離不開水,但是沒有說不離開哪滴水.
          posts - 98,comments - 104,trackbacks - 0

          很多核心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 類在獨立的線程中調用這兩個方法。

          1. public class Common {  
          2.    
          3. public synchronized void synchronizedMethod1() {  
          4. System.out.println ("synchronizedMethod1 called");  
          5. try {  
          6. Thread.sleep (1000);  
          7. } catch (InterruptedException e) {  
          8. e.printStackTrace ();  
          9. }  
          10. System.out.println ("synchronizedMethod1 done");  
          11. }  
          12. public void method1() {  
          13. System.out.println ("Method 1 called");  
          14. try {  
          15. Thread.sleep (1000);  
          16. } catch (InterruptedException e) {  
          17. e.printStackTrace ();  
          18. }  
          19. System.out.println ("Method 1 done");  
          20. }  
          1. public class MyThread extends Thread {  
          2. private int id = 0;  
          3. private Common common;  
          4.    
          5. public MyThread (String name, int no, Common object) {  
          6. super(name);  
          7. common = object;  
          8. id = no;  
          9. }  
          10.    
          11. public void run () {  
          12. System.out.println ("Running Thread" + this.getName ());  
          13. try {  
          14. if (id == 0) {  
          15. common.synchronizedMethod1();  
          16. } else {  
          17. common.method1();  
          18. }  
          19. } catch (Exception e) {  
          20. e.printStackTrace ();  
          21. }  
          22. }  
          23.    
          24. public static void main (String[] args) {  
          25. Common c = new Common ();  
          26. MyThread t1 = new MyThread ("MyThread-1", 0, c);  
          27. MyThread t2 = new MyThread ("MyThread-2", 1, c);  
          28. t1.start ();  
          29. t2.start ();  
          30. }  
          31. }  

          這里是程序的輸出:

          1. Running ThreadMyThread-1  
          2. synchronizedMethod1 called  
          3. Running ThreadMyThread-2  
          4. Method 1 called  
          5. synchronizedMethod1 done  
          6. Method 1 done 

           

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

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

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

          1. public class Common {  
          2. public synchronized void synchronizedMethod1() {  
          3. System.out.println ("synchronizedMethod1 called");  
          4. try {  
          5. Thread.sleep (1000);  
          6. } catch (InterruptedException e) {  
          7. e.printStackTrace ();  
          8. }  
          9. System.out.println ("synchronizedMethod1 done");  
          10. }  
          11.    
          12. public synchronized void synchronizedMethod2() {  
          13. System.out.println ("synchronizedMethod2 called");  
          14. try {  
          15. Thread.sleep (1000);  
          16. } catch (InterruptedException e) {  
          17. e.printStackTrace ();  
          18. }  
          19. System.out.println ("synchronizedMethod2 done");  
          20. }  
          1. public class MyThread extends Thread {  
          2. private int id = 0;  
          3. private Common common;  
          4.    
          5. public MyThread (String name, int no, Common object) {  
          6. super(name);  
          7. common = object;  
          8. id = no;  
          9. }  
          10.    
          11. public void run () {  
          12. System.out.println ("Running Thread" + this.getName ());  
          13. try {  
          14. if (id == 0) {  
          15. common.synchronizedMethod1();  
          16. } else {  
          17. common.synchronizedMethod2();  
          18. }  
          19. } catch (Exception e) {  
          20. e.printStackTrace ();  
          21. }  
          22. }  
          23.    
          24. public static void main (String[] args) {  
          25. Common c = new Common ();  
          26. MyThread t1 = new MyThread ("MyThread-1", 0, c);  
          27. MyThread t2 = new MyThread ("MyThread-2", 1, c);  
          28. t1.start ();  
          29. t2.start ();  
          30. }  

          10.什么是死鎖

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

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

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

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

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

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

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

          sd.csdn.net/a/20120528/2806046.html
          posted on 2012-06-14 19:00 ゞ沉默是金ゞ 閱讀(276) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 岑巩县| 乌兰县| 重庆市| 萍乡市| 东乡族自治县| 准格尔旗| 通江县| 巢湖市| 武宣县| 曲靖市| 普定县| 隆子县| 泸西县| 庆城县| 巧家县| 泸定县| 开封县| 宜阳县| 鄄城县| 泰兴市| 军事| 得荣县| 驻马店市| 二连浩特市| 侯马市| 乐亭县| 黑水县| 冀州市| 六盘水市| 桐庐县| 云安县| 晋中市| 江陵县| 那曲县| 定兴县| 大城县| 根河市| 四子王旗| 淮安市| 都昌县| 沾化县|