1. 程式人生 > >Java多執行緒面試題整理

Java多執行緒面試題整理

1、什麼是多執行緒

執行緒是作業系統中排程的基本單位

2、執行緒和程序的區別

執行緒是排程的基本單位,而程序是資源分配的基本單位;

3、java如何建立執行緒

  1. 繼承java.lang.Thread類
  2. 實現Runnable介面的run()方法

注:由於java只能實現單繼承,如果已經繼承了一個類,同時還需要建立執行緒,則需要使用第二種方法。

4、Thread 類中的start() 和 run() 方法有什麼區別?

呼叫start()方法會建立一個新執行緒,run()方法只會呼叫已經存在的執行緒,start()方法中包含了run()方法的呼叫過程

5、什麼是執行緒安全?

如果你的程式碼所在的程序中有多個執行緒在同時執行,而這些執行緒可能會同時執行這段程式碼。如果每次執行結果和單執行緒執行的結果是一樣的,而且其他的變數的值也和預期的是一樣的,就是執行緒安全的。存在競爭的執行緒不安全,不存在競爭的執行緒就是安全的

6、Java中什麼是競態條件? 舉個例子說明。

多執行緒對一些資源的競爭的時候就會產生競態條件,如果首先要執行的程式競爭失敗排到後面執行了,那麼整個程式就會出現一些不確定的bugs。這種bugs很難發現而且會重複出現,因為執行緒間的隨機競爭。一個例子就是無序處理。

7、Java中如何停止一個執行緒?

java中不存在停止執行緒的API,當run() 或者 call() 方法執行完的時候執行緒會自動結束,如果要手動結束一個執行緒,你可以用volatile 布林變數來退出run()方法的迴圈或者是取消任務來中斷執行緒。

8、 一個執行緒執行時發生異常會怎樣?

簡單的說,如果異常沒有被捕獲該執行緒將會停止執行。

9、如何在兩個執行緒間共享資料?

可以通過共享物件來實現這個目的,或者是使用像阻塞佇列這樣併發的資料結構。或者可以用wait和notify方法實現了生產者消費者模型。

10、什麼是執行緒池? 為什麼要使用它?

建立執行緒要花費昂貴的資源和時間,如果任務來了才建立執行緒那麼響應時間會變長,而且一個程序能建立的執行緒數有限。為了避免這些問題,在程式啟動的時候就建立若干執行緒來響應處理,它們被稱為執行緒池,裡面的執行緒叫工作執行緒。從JDK1.5開始,Java API提供了Executor框架讓你可以建立不同的執行緒池。比如單執行緒池,每次處理一個任務;數目固定的執行緒池或者是快取執行緒池(一個適合很多生存期短的任務的程式的可擴充套件執行緒池)。

11、 如何避免死鎖?

  Java多執行緒中的死鎖 死鎖是指兩個或兩個以上的程序在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。這是一個嚴重的問題,因為死鎖會讓你的程式掛起無法完成任務,死鎖的發生必須滿足以下四個條件:

  • 互斥條件:一個資源每次只能被一個程序使用。
  • 請求與保持條件:一個程序因請求資源而阻塞時,對已獲得的資源保持不放。
  • 不剝奪條件:程序已獲得的資源,在末使用完之前,不能強行剝奪。
  • 迴圈等待條件:若干程序之間形成一種頭尾相接的迴圈等待資源關係。

避免死鎖最簡單的方法就是阻止迴圈等待條件,將系統中所有的資源設定標誌位、排序,規定所有的程序申請資源必須以一定的順序(升序或降序)做操作來避免死鎖。

12、Java中活鎖和死鎖有什麼區別?

活鎖和死鎖類似,不同之處在於處於活鎖的執行緒或程序的狀態是不斷改變的。一個現實的活鎖例子是兩個人在狹小的走廊碰到,兩個人都試著避讓對方好讓彼此通過,但是因為避讓的方向都一樣導致最後誰都不能通過走廊。

13、怎麼檢測一個執行緒是否擁有鎖?

在java.lang.Thread中有一個方法叫holdsLock(),如果當前執行緒擁有某個具體物件的鎖,則返回true

14、什麼是阻塞式方法?

阻塞式方法是指程式會一直等待該方法完成期間不做其他事情,ServerSocket的accept()方法就是一直等待客戶端連線。這裡的阻塞是指呼叫結果返回之前,當前執行緒會被掛起,直到得到結果之後才會返回。此外,還有非同步和非阻塞式方法在任務完成前就返回。

15、多執行緒中的忙迴圈是什麼?

  忙迴圈就是程式設計師用迴圈讓一個執行緒等待,不像傳統方法wait(), sleep() 或 yield() 它們都放棄了CPU控制,而忙迴圈不會放棄CPU,它就是在執行一個空迴圈。這麼做的目的是為了保留CPU快取,在多核系統中,一個等待執行緒醒來的時候可能會在另一個核心執行,這樣會重建快取。為了避免重建快取和減少等待重建的時間就可以使用它了。