您好,登錄后才能下訂單哦!
這篇文章主要講解了“2021最新版多線程的面試題有哪些”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“2021最新版多線程的面試題有哪些”吧!
1)發揮多核CPU 的優勢
隨著工業的進步,現在的筆記本、臺式機乃至商用的應用服務器至少也都是雙核的,4 核、8 核甚至 16 核的也都不少見,如果是單線程的程序,那么在雙核 CPU 上 就浪費了 50%, 在 4 核 CPU 上就浪費了 75%。單核 CPU 上所謂的"多線程"那是假的多線程,同一時間處理器只會處理一段邏輯,只不過線程之間切換得比較快, 看著像多個線程"同時"運行罷了。多核 CPU 上的多線程才是真正的多線程,它能讓你的多段邏輯同時工作,多線程,可以真正發揮出多核CPU 的優勢來,達到充分利用CPU 的目的。
2)防止阻塞
從程序運行效率的角度來看,單核 CPU 不但不會發揮出多線程的優勢,反而會因為在單核CPU 上運行多線程導致線程上下文的切換,而降低程序整體的效率。但
是單核 CPU 我們還是要應用多線程,就是為了防止阻塞。試想,如果單核 CPU 使用單線程,那么只要這個線程阻塞了,比方說遠程讀取某個數據吧,對端遲遲未返回又沒有設置超時時間,那么你的整個程序在數據返回回來之前就停止運行了。多線程可以防止這個問題,多條線程同時運行,哪怕一條線程的代碼執行讀取數據阻塞,也不會影響其它任務的執行。
3)便于建模
這是另外一個沒有這么明顯的優點了。假設有一個大的任務 A,單線程編程,那么就要考慮很多,建立整個程序模型比較麻煩。但是如果把這個大的任務 A 分解成幾個小任務,任務B、任務 C、任務 D,分別建立程序模型,并通過多線程分別運行這幾個任務,那就簡單很多了。
進程和線程的主要差別在于它們是不同的操作系統資源管理方式。進程有獨立的地址空間,一個進程崩潰后,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進程死掉,所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對于一些要求同時進行并且又要共享某些變量的并發操作,只能用線程,不能用進程。
1)繼承 Thread 類實現多線程
2)實現 Runnable 接口方式實現多線程
3)使用 ExecutorService、Callable、Future 實現有返回結果的多線程
只有調用了 start()方法,才會表現出多線程的特性,不同線程的 run()方法里面的代碼交替執行。如果只是調用 run()方法,那么代碼還是同步執行的,必須等待一個線程的 run()方法里面的代碼全部執行完畢之后,另外一個線程才可以執行其 run()方法里面的代碼。
stop 終止,不推薦。
NEW:毫無疑問表示的是剛創建的線程,還沒有開始啟動。
RUNNABLE: 表示線程已經觸發 start()方式調用,線程正式啟動,線程處于運行中狀態。
BLOCKED:表示線程阻塞,等待獲取鎖,如碰到 synchronized、lock 等關鍵字等占用臨界區的情況,一旦獲取到鎖就進行 RUNNABLE 狀態繼續運行。
WAITING:表示線程處于無限制等待狀態,等待一個特殊的事件來重新喚醒,如通過wait()方法進行等待的線程等待一個 notify()或者 notifyAll()方法,通過 join()方法進行等待的線程等待目標線程運行結束而喚醒,一旦通過相關事件喚醒線程,線程就進入了 RUNNABLE 狀態繼續運行。
TIMED_WAITING:表示線程進入了一個有時限的等待,如 sleep(3000),等待 3 秒后線程重新進行 RUNNABLE 狀態繼續運行。
TERMINATED:表示線程執行完畢后,進行終止狀態。需要注意的是,一旦線程通過 start 方法啟動后就再也不能回到初始 NEW 狀態,線程終止后也不能再回到 RUNNABLE 狀態
這個問題常問,sleep 方法和 wait 方法都可以用來放棄 CPU 一定的時間,不同點在于如果線程持有某個對象的監視器,sleep 方法不會放棄這個對象的監視器,wait 方法會放棄這個對象的監視器
Synchronized 關鍵字,Lock 鎖實現,分布式鎖等。
死鎖就是兩個線程相互等待對方釋放對象鎖。
wait/notify
實現Callable 接口。
用 join 方法。
用 Semaphore。
我們知道不用線程池的話,每個線程都要通過 new Thread(xxRunnable).start()的方式來創建并運行一個線程,線程少的話這不會是問題,而真實環境可能會開啟多個1線程讓系統和程序達到最佳效率,當線程數達到一定數量就會耗盡系統的 CPU 和內存資源,也會造成 GC頻繁收集和停頓,因為每次創建和銷毀一個線程都是要消 耗系統資源的,如果為每個任務都創建線程這無疑是一個很大的性能瓶頸。所以,線程池中的線程復用極大節省了系統資源,當線程一段時間不再有任務處理時它也 會自動銷毀,而不會長駐內存。
兩個看上去有點像的類,都在 java.util.concurrent 下,都可以用來表示代碼運行到某個點上,二者的區別在于:
1.CyclicBarrier 的某個線程運行到某個點上之后,該線程即停止運行,直到所有的線程都到達了這個點,所有線程才重新運行;CountDownLatch 則不是,某線程運 行到某個點上之后,只是給某個數值-1 而已,該線程繼續運行1
2.CyclicBarrier 只能喚起一個任務,CountDownLatch 可以喚起多個任務
3.CyclicBarrier 可 重 用 , CountDownLatch 不 可 重 用 , 計 數 值 為 0 該CountDownLatch就不可再用了
什么是守護線程?與守護線程相對應的就是用戶線程,守護線程就是守護用戶線程,當用戶線程全部執行完結束之后,守護線程才會跟著結束。也就是守護線程必 須伴隨著用戶線程,如果一個應用內只存在一個守護線程,沒有用戶線程,守護線程自然會退出。
如果異常沒有被捕獲該線程將會停止執行。Thread.UncaughtExceptionHandler 是用于處理未捕獲異常造成線程突然中斷情況的一個內嵌接口。當一個未捕獲異常將造 成線程中斷的時 候 JVM 會 使 用 Thread.getUncaughtExceptionHandler() 來 查 詢 線程 的UncaughtExceptionHandler 并 將 線 程 和 異 常 作 為 參 數 傳 遞 給 handler 的 uncaughtException()方法進行處理。
Yield 方法可以暫停當前正在執行的線程對象,讓其它有相同優先級的線程執行。它是一個靜態方法而且只保證當前線程放棄 CPU 占用而不能保證使其它線程一定 能占用 CPU,執行yield()的線程有可能在進入到暫停狀態后馬上又被執行。
所謂重入鎖,指的是以線程為單位,當一個線程獲取對象鎖之后,這個線程可以再次獲取本對象上的鎖,而其他的線程是不可以的。
鎖類、鎖方法、鎖代碼塊
大任務自動分散小任務,并發執行,合并小任務結果。
線程過多會造成棧溢出,也有可能會造成堆異常
Java 中平時用的最多的 Map 集合就是 HashMap 了,它是線程不安全的。 看下面兩個場景:
1、當用在方法內的局部變量時,局部變量屬于當前線程級別的變量,其他線程訪問不了,所以這時也不存在線程安全不安全的問題了。1
2、當用在單例對象成員變量的時候呢?這時候多個線程過來訪問的就是同一個HashMap 了,對同個 HashMap 操作這時候就存在線程安全的問題了。
java.lang.Thread#holdsLock 方法
jstack
1、盡量縮小同步的范圍,增加系統吞吐量。
2、分布式同步鎖無意義,要使用分布式鎖。
3、防止死鎖,注意加鎖順序。
要在同步塊中使用。
如果任務拆解的很深,系統內的線程數量堆積,導致系統性能性能嚴重下降;如果函數的調用棧很深,會導致棧內存溢出;
synchronized 和 viotatile
ReentrantLock、ReadWriteLock
ThreadLocal 的作用是提供線程內的局部變量,這種變量在線程的生命周期內起作用,減少同一個線程內多個函數或者組件之間一些公共變量的傳遞的復雜度。用來解決數據庫連接、Session 管理等。
ReadWriteLock 是一個讀寫鎖接口,ReentrantReadWriteLock 是 ReadWriteLock 接口的一個具體實現,實現了讀寫的分離,讀鎖是共享的,寫鎖是獨占的,讀和讀之間不會互斥,讀和寫、寫和讀、寫和寫之間才會互斥,提升了讀寫的性能。
FutureTask 表示一個異步運算的任務,FutureTask 里面可以傳入一個 Callable 的具1體實現類,可以對這個異步運算的任務的結果進行等待獲取、判斷是否已經完成、取消任務等操作。
自旋鎖是采用讓當前線程不停地的在循環體內執行實現的,當循環的條件被其他線程改變時才能進入臨界區。
Java 不支持類的多重繼承,但允許你實現多個接口。所以如果你要繼承其他類,也為了減少類之間的耦合性,Runnable 會更好。
notify()方法不能喚醒某個具體的線程,所以只有一個線程在等待的時候它才有用武之地。
而 notifyAll()喚醒所有線程并允許他們爭奪鎖確保了至少有一個線程能繼續運行。
阻塞式方法是指程序會一直等待該方法完成期間不做其他事情,ServerSocket 的accept()方法就是一直等待客戶端連接。這里的阻塞是指調用結果返回之前,當前
線程會被掛起,直到得到結果之后才會返回。此外,還有異步和非阻塞式方法在任務完成前就返回。
當線程數小于最大線程池數 maximumPoolSize 時就會創建新線程來處理,而線程數大于等于最大線程池數 maximumPoolSize 時就會執行拒絕策略。
感謝各位的閱讀,以上就是“2021最新版多線程的面試題有哪些”的內容了,經過本文的學習后,相信大家對2021最新版多線程的面試題有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。