日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多线程常见问题总结

發布時間:2024/2/28 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程常见问题总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

多線程常見問題總結


目錄

  • 并行和并發有什么區別?
  • 線程和進程的區別?
  • 守護線程是什么?
  • 創建線程有幾種方式?
  • 說一下 rannable 和 callable 有什么區別?
  • 線程有哪些狀態?
  • sleep() 和 wait() 有什么區別?
  • notify() 和 notifyAll 有什么區別?
  • 線程的 run() 和 start() 有什么區別?
  • 創建線程池有哪幾種方式?
  • 線程池都有哪些狀態?
  • 線程池中 submit() 和 execute() 方法有什么區別?
  • 在 java 程序中怎么保證多線程的運行安全?
  • 多線程鎖的升級原理是什么?
  • 什么是死鎖?
  • 怎么防止死鎖?
  • TreadLocal 是什么?有哪些使用場景?
  • 說一下 synchronized 底層實現原理?
  • synchronized 和 volatile 的區別是什么?
  • synchronized 和 Lock 有什么區別?
  • synchronized 和 ReentrantLock 區別是什么?
  • 說一下 atomic 的原理?

  • 1. 并行和并發有什么區別?

    • 并行:多個處理器或多核處理器同時處理多個任務。
    • 并發:多個任務在同一個cpu核上,按細分的時間片輪流執行,從邏輯上看那些任務是同時執行。

      并發:兩個隊列和一臺咖啡機。
      并行:兩個隊列和兩臺咖啡機。

    2. 線程和進程的區別?

  • 進程是資源分配的最小單位,線程是程序執行的最小單位。
  • 開銷方面:每個進程都有獨立的代碼和數據空間,程序之間的切換會有較大的開銷;線程可以看作是輕量級進程,同一類線程共享代碼和數據空間,每個線程都有自己獨立的運行棧和程序計數器,線程之間切換開銷小。
  • 所處環境:在操作系統中能同時運行多個進程;而在同一個進程中有多個線程同時執行(通過CPU調度,在每個時間片只有一個線程執行)
  • 內存分配:系統在運行的時候會為每個進程分配不同的內存空間;對線程而言,除CPU外,系統不會為線程分配內存(線程所使用的資源來自其所屬進程的資源),線程之間只能共享資源。
  • 包含關系:一個進程可以有多個線程,線程是進程的一部分,所有線程也稱為輕量級進程。

  • 3. 守護線程是什么?

    守護線程是運行在后臺的一種特殊進程。它獨立于控制終端并且周期性地執行某種任務或等待處理某些發生的事件。在 java 中垃圾收回線程就是特殊的守護線程。


    4. 創建線程有幾種方式?

    創建線程有三種方式:

    • 繼承Thread 重寫 run 方法。
    • 實現 Runnable 接口。
    • 實現 Callable 接口。

    5. 說一下 rannable 和 callable 有什么區別?

    runnable 沒有返回值,callable 可以拿到有返回值,callable 可以看作是 runnable 的補充。


    6. 線程有哪些狀態?

    線程的狀態:

    • NEW:尚未啟動
    • RUNNABLE:正在執行
    • BLOCKED:阻塞的(被同步鎖或IO鎖阻塞)
    • WAITING:永久等待狀態
    • TIMED_WAITING:等待指定的時間重新被喚醒的狀態
    • TERMINATED:執行完成

    7. sleep() 和 wait() 有什么區別?

    • 類的不同:sleep() 來自 Thread,wait() 來自 Object。
    • 釋放鎖:sleep() 不釋放鎖;wait() 釋放鎖。
    • 用法不同:sleep() 時間到會自動恢復;wait() 可以使用 notify/ notifyAll 直接喚醒。

    8. notify() 和 notifyAll 有什么區別?

  • notifyAll()會喚醒所有的線程,notify()之后會喚醒一個線程。
  • notifyAll()調用后,會將所有線程由等待池移到鎖池,然后參與鎖的競爭,競爭成功則繼續執行,如果不成功則留在鎖池等待鎖被釋放后再次參與競爭。而notify()只會喚醒一個線程,具體喚醒哪一個線程由虛擬機控制。

  • 9. 線程的 run() 和 start() 有什么區別?

    start() 方法用于啟動線程,run() 方法用于執行線程的運行時代碼。run() 可以重復調用,start()方法只能調用一次。


    10. 創建線程池有哪幾種方式?

    線程池創建有七種方式,最核心的是最后一種:

    • newSingleThreadExecutor():它的特點在于工作線程數目被限制為1,操作一個無界的工作隊列,所以它保證了所有任務都是被順序執行,最多會有一個任務處于活動狀態,并且不允許使用者改動線程池實例,因此可以避免其改變線程數量。
    • newCachedThreadPool():它是一種用來處理大量短時間工作任務的線程池,具有幾個鮮明的特點:它會試圖緩存線程并重用,當無緩存線程可用時,就會創建新的工作線程;如果線程閑置的時間超過60s,則被終止并移出緩存;長時間閑置的,這種線程池,不會消耗什么資源。其內部使用SynchronousQueue作為工作隊列;
    • newFixedThreadPool(int nTreands):重用指定數目的線程,其背后使用的是無界的工作隊列,任何時候最多有 nThread 個工作線程是活動的。這意味著,如果任務數量超過了活動隊列數目,將在工作隊列中等待空閑線程出現;如果有工作線程退出,將會有新的工作線程被創建,以補足指定的數目 nThread;
    • newSingleThreadScheduleExecutor():創建單線程池,返回ScheduledExecutorService,可以進行定時或周期性的工作調度;
    • newSchduleThreadPool(int corePoolSize):和newSingleThreadScheduleExecutor() 類似,創建的是個 ScheduledExecutorService,可以進行定時或周期性的工作調度,區別在于單一工作線程還是多個工作線程;
    • newWorkStealingPool(int parallelism):這是一個經常被人忽略的線程池,Java 8 才加入這個創建方法,其內部會構建 ForkJoinPool,利用 Work-Stealing 算法,并行地處理任務,不保證處理順序。
    • TreadPoolExecutor():是最原始的線程池創建,上面1-3創建方法都是對TreadPoolExecutor的封裝。

    11. 線程池都有哪些狀態?

    • RUNNING:這是最正常的狀態,接受新的任務,處理等待隊列中的任務。
    • SHUTDOWN:不接受新的任務提交,但是會繼續處理等待隊列中的任務。
    • STOP:不接受新的任務提交,不再處理等待隊列中的任務,中斷正在執行的線程。
    • TIDYING:所有的任務都銷毀了,workCount為0,線程池的狀態再轉換為TIDYING狀態時,會執行鉤子方法 terminated()。
    • TERMINATED:terminated() 方法結束后,線程池的狀態就會變成這個。

    12. 線程池中 submit() 和 execute() 方法有什么區別?

    • execute():只能執行 Runnable 類型的任務。
    • submit():可以執行 Runnable 和 Callable 類型的任務。

    Callable 類型的任務可以獲取執行的返回值,而 Runnable 執行無返回值。


    13. 在 java 程序中怎么保證多線程的運行安全?

    • 方法一:使用安全類,比如 Java.util.concurrent 下的類。
    • 方法二:使用自動鎖 synchronized。
    • 方法三:使用手動鎖 Lock。


    14. 多線程鎖的升級原理是什么?

    synchronized 鎖升級原理:在鎖對象的對象頭里面有一個 threadid 字段,在第一次訪問的時候 threadid 為空,jvm讓其持有偏向鎖,并將 threadid 設置為其線程 id,再次進入的時候會先判斷 threadid 是否與其線程 id 一致,如果一致則可以直接使用此對象,如果不一致,則升級偏向鎖為輕量級鎖,通過自旋循環一定次數來獲取鎖,執行一定次數之后,如果還沒有正常獲取到要使用的對象,此時就把鎖從輕量級升級為重量級鎖,此過程就構成了 synchronized 鎖的升級。

    鎖的升級目的:鎖升級是為了減低鎖帶來的性能消耗。在 java 6 之后優化 synchronized 的實現方法,使用了偏向鎖升級為輕量級鎖再升級到重量級鎖的方法,從而降低了鎖帶來的性能消耗。


    15. 什么是死鎖?

    當線程 A 持有獨占鎖a,并嘗試去獲取獨占鎖 b 的同時,線程 B 持有獨占鎖 b,并嘗試獲取獨占鎖 a 的情況下,就會發生 AB 兩個線程由于相互持有對方需要的鎖,而發生阻塞現象,我們稱為死鎖。


    16. 怎么防止死鎖?

    • 盡量使用 tryLock(long timeout, TimeUnit unit) 的方法(ReentrantLock、ReentrantReadWriteLock),設置超時時間,超時可以退出防止死鎖。
    • 盡量使用 Java.util.concurrent 并發類代替自己手寫鎖。
    • 盡量降低鎖的粒度,盡量不要幾個功能用同一把鎖。
    • 盡量減少同步的代碼塊。

    17. TreadLocal 是什么?有哪些使用場景?

    ThreadLocal 為每個使用該變量的線程提供獨立的變量副本,所以每一個線程都可以獨立地改變自己的副本,而不會影響其他線程所對應的副本。

    ThreadLocal 的經典使用場景是數據庫連接和session 管理等。


    18. 說一下 synchronized 底層實現原理?

    synchronized 是由一對 monitorenter/monitorexit 指令實現的,monitor 對象是同步的基本單元。在Java 6 之前,monitor 的實現完全依靠操作系統內部的互斥鎖,因此需要進行用戶態到內核態的切換,所以同步操作是一個無差別的重量級操作,性能也很低。但在 java 6 的時候,Java 虛擬機對此進行了改進,提供了三種不同的 monitor 實現,也就是常說的三種不同的鎖:偏向鎖(Biased Locking)、輕量級鎖和重量級鎖,大大改進其性能。

    • 偏向鎖:無實際競爭,且將來只有第一個申請鎖的線程會使用鎖。
    • 輕量級鎖:無實際競爭,多個線程交替使用鎖;允許短時間的鎖競爭。
    • 重量級鎖:有實際競爭,且鎖競爭時間長。

    19. synchronized 和 volatile 的區別是什么?

    • volatile 是變量修飾符;synchronized是修飾類,方法,代碼塊。
    • volatile 僅能實現變量的修改可見性,不能保證原子性;而 synchronized 則可以保證變量的修改可見性和原子性。
    • volatile 不會造成線程阻塞;synchronized 可能會造成線程的阻塞。

    20. synchronized 和 Lock 有什么區別?

    • synchronized 可以給類、方法、代碼塊加鎖;而 lock 只能給代碼塊加鎖。
    • synchronized 不需要手動獲取鎖和釋放鎖,使用簡單,發送異常會自動釋放鎖,不會造成死鎖;而 lock 需要自己加鎖和釋放鎖,如果使用不當沒有 unLock() 去釋放鎖就會造成死鎖。
    • 通過 Lock 可以知道有沒有成功獲取鎖,而 synchronized 無法辦到。

    21. synchronized 和 ReentrantLock 區別是什么?

    synchronized 早期實現比較低效,對比 ReentrantLock,大多數場景性能都相差較大,但是在 java 6 中對synchronized 進行了非常多的改進。

    主要區別如下:

  • 原始構成:synchronized 是關鍵字屬于 JVM 層面,由一對 monitorenter/monitorexit 指令實現,底層通過 monitor 對象完成。而 Lock 是具體類(java.util.concurrent.locks.Lock),屬于 api 層面的鎖。
  • 使用方法:synchronized 不需要手動釋放鎖,當 synchronized 代碼執行完成后系統會自動讓線程釋放對鎖的占用。ReentrantLock 則需要用戶手動釋放鎖,若沒有主動釋放鎖,就可能導致死鎖現象。需要 lock() 和 unLock() 方法配合 try/finally 語句塊來完成。
  • 等待是否可以中斷:synchronized 不可中斷,除非拋出異常或者正常運行完成。ReentrantLock 可中斷。1. 設置超時時間方法 tryLock(Long timeout, TimeUnit unit) 2.lockInterruptibly()放代碼塊中,調用interrupt()方法中斷。
  • 加鎖是否公平:synchronized 是非公平鎖。ReentrantLock 兩者都可以,默認非公平鎖,構造方法可以傳入 boolean 值,true值為公平鎖,false 為非公平鎖。
  • 鎖綁定多個條件 Condition:synchronized 沒有。ReentrantLock 用來實現分組喚醒需要喚醒的線程,可以精準喚醒,而不是像 synchronized 要么隨機喚醒一個線程要么全部喚醒線程。
  • 修飾對象:synchronized 可用于修飾方法,代碼塊等。ReentrantLock 只適用于代碼塊鎖。
  • Lock 相比較 synchronized 的優點

  • ReentrantLock 可以中斷線程。
  • ReentrantLock 可以精準喚醒線程。

  • 22. 說一下 atomic 的原理?

    atomic 主要利用 CAS(Compare And Swap)和 volatile 和 native 方法來保證原子操作,從而避免 synchronized 的高開銷,執行效率大為提高。

    總結

    以上是生活随笔為你收集整理的多线程常见问题总结的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。