主頁 > 後端開發 > 那些面試官必問的JAVA多執行緒和并發面試題及回答

那些面試官必問的JAVA多執行緒和并發面試題及回答

2020-10-18 21:02:44 後端開發

Java多執行緒面試問題

timg (1).jpg

1. 行程和執行緒之間有什么不同?
一個行程是一個獨立(self contained)的運行環境,它可以被看作一個程式或者一個應用,而執行緒是在行程中執行的一個任務,Java運行環境是一個包含了不同的類和程式的單一行程,執行緒可以被稱為輕量級行程,執行緒需要較少的資源來創建和駐留在行程中,并且可以共享行程中的資源,

2. 多執行緒編程的好處是什么?
在多執行緒程式中,多個執行緒被并發的執行以提高程式的效率,CPU不會因為某個執行緒需要等待資源而進入空閑狀態,多個執行緒共享堆記憶體(heap memory),因此創建多個執行緒去執行一些任務會比創建多個行程更好,舉個例子,Servlets比CGI更好,是因為Servlets支持多執行緒而CGI不支持,

3. 用戶執行緒和守護執行緒有什么區別?
當我們在Java程式中創建一個執行緒,它就被稱為用戶執行緒,一個守護執行緒是在后臺執行并且不會阻止JVM終止的執行緒,當沒有用戶執行緒在運行的時候,JVM關閉程式并且退出,一個守護執行緒創建的子執行緒依然是守護執行緒,

4. 我們如何創建一個執行緒?
有兩種創建執行緒的方法:一是實作Runnable介面,然后將它傳遞給Thread的建構式,創建一個Thread物件;二是直接繼承Thread類,

5. 有哪些不同的執行緒生命周期?
當我們在Java程式中新建一個執行緒時,它的狀態是New,當我們呼叫執行緒的start()方法時,狀態被改變為Runnable,執行緒調度器會為Runnable執行緒池中的執行緒分配CPU時間并且講它們的狀態改變為Running,其他的執行緒狀態還有Waiting,Blocked 和Dead,
6. 可以直接呼叫Thread類的run()方法么?
當然可以,但是如果我們呼叫了Thread的run()方法,它的行為就會和普通的方法一樣,為了在新的執行緒中執行我們的代碼,必須使用Thread.start()方法,

7. 如何讓正在運行的執行緒暫停一段時間?
我們可以使用Thread類的Sleep()方法讓執行緒暫停一段時間,需要注意的是,這并不會讓執行緒終止,一旦從休眠中喚醒執行緒,執行緒的狀態將會被改變為Runnable,并且根據執行緒調度,它將得到執行,

8. 你對執行緒優先級的理解是什么?
每一個執行緒都是有優先級的,一般來說,高優先級的執行緒在運行時會具有優先權,但這依賴于執行緒調度的實作,這個實作是和作業系統相關的(OS dependent),我們可以定義執行緒的優先級,但是這并不能保證高優先級的執行緒會在低優先級的執行緒前執行,執行緒優先級是一個int變數(從1-10),1代表最低優先級,10代表最高優先級,

9. 什么是執行緒調度器(Thread Scheduler)和時間分片(Time Slicing)?
執行緒調度器是一個作業系統服務,它負責為Runnable狀態的執行緒分配CPU時間,一旦我們創建一個執行緒并啟動它,它的執行便依賴于執行緒調度器的實作,時間分片是指將可用的CPU時間分配給可用的Runnable執行緒的程序,分配CPU時間可以基于執行緒優先級或者執行緒等待的時間,執行緒調度并不受到Java虛擬機控制,所以由應用程式來控制它是更好的選擇(也就是說不要讓你的程式依賴于執行緒的優先級),

10. 在多執行緒中,什么是背景關系切換(context-switching)?
背景關系切換是存盤和恢復CPU狀態的程序,它使得執行緒執行能夠從中斷點恢復執行,背景關系切換是多任務作業系統和多執行緒環境的基本特征,

11. 你如何確保main()方法所在的執行緒是Java程式最后結束的執行緒?
我們可以使用Thread類的joint()方法來確保所有程式創建的執行緒在main()方法退出前結束,
12.執行緒之間是如何通信的?
當執行緒間是可以共享資源時,執行緒間通信是協調它們的重要的手段,Object類中wait()\notify()\notifyAll()方法可以用于執行緒間通信關于資源的鎖的狀態,

13.為什么執行緒通信的方法wait(), notify()和notifyAll()被定義在Object類里?
Java的每個物件中都有一個鎖(monitor,也可以成為監視器) 并且wait(),notify()等方法用于等待物件的鎖或者通知其他執行緒物件的監視器可用,在Java的執行緒中并沒有可供任何物件使用的鎖和同步器,這就是為什么這些方法是Object類的一部分,這樣Java的每一個類都有用于執行緒間通信的基本方法

14. 為什么wait(), notify()和notifyAll()必須在同步方法或者同步塊中被呼叫?
當一個執行緒需要呼叫物件的wait()方法的時候,這個執行緒必須擁有該物件的鎖,接著它就會釋放這個物件鎖并進入等待狀態直到其他執行緒呼叫這個物件上的notify()方法,同樣的,當一個執行緒需要呼叫物件的notify()方法時,它會釋放這個物件的鎖,以便其他在等待的執行緒就可以得到這個物件鎖,由于所有的這些方法都需要執行緒持有物件的鎖,這樣就只能通過同步來實作,所以他們只能在同步方法或者同步塊中被呼叫,

15. 為什么Thread類的sleep()和yield()方法是靜態的?
Thread類的sleep()和yield()方法將在當前正在執行的執行緒上運行,所以在其他處于等待狀態的執行緒上呼叫這些方法是沒有意義的,這就是為什么這些方法是靜態的,它們可以在當前正在執行的執行緒中作業,并避免程式員錯誤的認為可以在其他非運行執行緒呼叫這些方法,

16.如何確保執行緒安全?
在Java中可以有很多方法來保證執行緒安全——同步,使用原子類(atomic concurrent classes),實作并發鎖,使用volatile關鍵字,使用不變類和執行緒安全類,
17. volatile關鍵字在Java中有什么作用?
當我們使用volatile關鍵字去修飾變數的時候,所以執行緒都會直接讀取該變數并且不快取它,這就確保了執行緒讀取到的變數是同記憶體中是一致的,

18. 同步方法和同步塊,哪個是更好的選擇?
同步塊是更好的選擇,因為它不會鎖住整個物件(當然你也可以讓它鎖住整個物件),同步方法會鎖住整個物件,哪怕這個類中有多個不相關聯的同步塊,這通常會導致他們停止執行并需要等待獲得這個物件上的鎖,

19.如何創建守護執行緒?
使用Thread類的setDaemon(true)方法可以將執行緒設定為守護執行緒,需要注意的是,需要在呼叫start()方法前呼叫這個方法,否則會拋出IllegalThreadStateException例外,

20. 什么是ThreadLocal?
ThreadLocal用于創建執行緒的本地變數,我們知道一個物件的所有執行緒會共享它的全域變數,所以這些變數不是執行緒安全的,我們可以使用同步技術,但是當我們不想使用同步的時候,我們可以選擇ThreadLocal變數,

每個執行緒都會擁有他們自己的Thread變數,它們可以使用get()\set()方法去獲取他們的默認值或者在執行緒內部改變他們的值,ThreadLocal實體通常是希望它們同執行緒狀態關聯起來是private static屬性,
21. 什么是Thread Group?為什么建議使用它?
ThreadGroup是一個類,它的目的是提供關于執行緒組的資訊,

ThreadGroup API比較薄弱,它并沒有比Thread提供了更多的功能,它有兩個主要的功能:一是獲取執行緒組中處于活躍狀態執行緒的串列;二是設定為執行緒設定未捕獲例外處理器(ncaught exception handler),但在Java 1.5中Thread類也添加了setUncaughtExceptionHandler(UncaughtExceptionHandler eh) 方法,所以ThreadGroup是已經過時的,不建議繼續使用,

t1.setUncaughtExceptionHandler(new UncaughtExceptionHandler(){

@Override

public void uncaughtException(Thread t, Throwable e) {

System.out.println("exception occured:"+e.getMessage());

}
});

22. 什么是Java執行緒轉儲(Thread Dump),如何得到它?
執行緒轉儲是一個JVM活動執行緒的串列,它對于分析系統瓶頸和死鎖非常有用,有很多方法可以獲取執行緒轉儲——使用Profiler,Kill -3命令,jstack工具等等,我更喜歡jstack工具,因為它容易使用并且是JDK自帶的,由于它是一個基于終端的工具,所以我們可以撰寫一些腳本去定時的產生執行緒轉儲以待分析,

23. 什么是死鎖(Deadlock)?如何分析和避免死鎖?
死鎖是指兩個以上的執行緒永遠阻塞的情況,這種情況產生至少需要兩個以上的執行緒和兩個以上的資源,

分析死鎖,我們需要查看Java應用程式的執行緒轉儲,我們需要找出那些狀態為BLOCKED的執行緒和他們等待的資源,每個資源都有一個唯一的id,用這個id我們可以找出哪些執行緒已經擁有了它的物件鎖,

避免嵌套鎖,只在需要的地方使用鎖和避免無限期等待是避免死鎖的通常辦法,

24. 什么是Java Timer類?如何創建一個有特定時間間隔的任務?
java.util.Timer是一個工具類,可以用于安排一個執行緒在未來的某個特定時間執行,Timer類可以用安排一次性任務或者周期任務,

java.util.TimerTask是一個實作了Runnable介面的抽象類,我們需要去繼承這個類來創建我們自己的定時任務并使用Timer去安排它的執行,

25. 什么是執行緒池?如何創建一個Java執行緒池?
一個執行緒池管理了一組作業執行緒,同時它還包括了一個用于放置等待執行的任務的佇列,

java.util.concurrent.Executors提供了一個 java.util.concurrent.Executor介面的實作用于創建執行緒池,

Java并發面試問題

u=3866461327,767826007&fm=26&gp=0.jpg

1. 什么是原子操作?在Java Concurrency API中有哪些原子類(atomic classes)?
原子操作是指一個不受其他操作影響的操作任務單元,原子操作是在多執行緒環境下避免資料不一致必須的手段,

int++并不是一個原子操作,所以當一個執行緒讀取它的值并加1時,另外一個執行緒有可能會讀到之前的值,這就會引發錯誤,

為了解決這個問題,必須保證增加操作是原子的,在JDK1.5之前我們可以使用同步技術來做到這一點,到JDK1.5,java.util.concurrent.atomic包提供了int和long型別的裝類,它們可以自動的保證對于他們的操作是原子的并且不需要使用同步,

2. Java Concurrency API中的Lock介面(Lock interface)是什么?對比同步它有什么優勢?
Lock介面比同步方法和同步塊提供了更具擴展性的鎖操作,他們允許更靈活的結構,可以具有完全不同的性質,并且可以支持多個相關類的條件物件,

它的優勢有:

可以使鎖更公平
可以使執行緒在等待鎖的時候回應中斷
可以讓執行緒嘗試獲取鎖,并在無法獲取鎖的時候立即回傳或者等待一段時間
可以在不同的范圍,以不同的順序獲取和釋放鎖

3. 什么是Executors框架?
Executor框架同java.util.concurrent.Executor 介面在Java 5中被引入,Executor框架是一個根據一組執行策略呼叫,調度,執行和控制的異步任務的框架,

無限制的創建執行緒會引起應用程式記憶體溢位,所以創建一個執行緒池是個更好的的解決方案,因為可以限制執行緒的數量并且可以回收再利用這些執行緒,利用Executors框架可以非常方便的創建一個執行緒池,

4. 什么是阻塞佇列?如何使用阻塞佇列來實作生產者-消費者模型?
java.util.concurrent.BlockingQueue的特性是:當佇列是空的時,從佇列中獲取或洗掉元素的操作將會被阻塞,或者當佇列是滿時,往佇列里添加元素的操作會被阻塞,

阻塞佇列不接受空值,當你嘗試向佇列中添加空值的時候,它會拋出NullPointerException,

阻塞佇列的實作都是執行緒安全的,所有的查詢方法都是原子的并且使用了內部鎖或者其他形式的并發控制,

BlockingQueue 介面是java collections框架的一部分,它主要用于實作生產者-消費者問題,

5. 什么是Callable和Future?
Java 5在concurrency包中引入了java.util.concurrent.Callable 介面,它和Runnable介面很相似,但它可以回傳一個物件或者拋出一個例外,

Callable介面使用泛型去定義它的回傳型別,Executors類提供了一些有用的方法去在執行緒池中執行Callable內的任務,由于Callable任務是并行的,我們必須等待它回傳的結果,java.util.concurrent.Future物件為我們解決了這個問題,在執行緒池提交Callable任務后回傳了一個Future物件,使用它我們可以知道Callable任務的狀態和得到Callable回傳的執行結果,Future提供了get()方法讓我們可以等待Callable結束并獲取它的執行結果,

6. 什么是FutureTask?
FutureTask是Future的一個基礎實作,我們可以將它同Executors使用處理異步任務,通常我們不需要使用FutureTask類,單當我們打算重寫Future介面的一些方法并保持原來基礎的實作是,它就變得非常有用,我們可以僅僅繼承于它并重寫我們需要的方法,
7.什么是并發容器的實作?
Java集合類都是快速失敗的,這就意味著當集合被改變且一個執行緒在使用迭代器遍歷集合的時候,迭代器的next()方法將拋出ConcurrentModificationException例外,
并發容器支持并發的遍歷和并發的更新,
主要的類有ConcurrentHashMap, CopyOnWriteArrayList 和CopyOnWriteArraySet,

8. Executors類是什么?
Executors為Executor,ExecutorService,ScheduledExecutorService,ThreadFactory和Callable類提供了一些工具方法,
Executors可以用于方便的創建執行緒池,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/178805.html

標籤:Java

上一篇:面向物件(2)

下一篇:這 30 個常用的 Maven 命令你必須熟悉!

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more