關於Java多線程的一些知識點總結

以下爲自己學習多線程的時候總結的一些知識點

同時推薦一本很好的關於多線程高併發的書籍:《Java高併發編程詳解》

  1. 線程的生命週期:創建,就緒,運行,阻塞,死亡
    新建狀態:當使用new關鍵字和Thread類或者子類建立了一個線程對象,該線程對象就處於新建狀態。它保持這個狀態直到程序start()這個線程。
    就緒狀態:當線程對象調用了start()方法之後,該線程就進入了就緒狀態。就緒狀態的線程處於就緒隊列中,要等待JVM裏的線程調度器的調度。
    運行狀態:如果就緒狀態的線程獲取CPU資源,就可以執行run(),此時線程便處於運行狀態。
    阻塞狀態:如果一個線程執行了sleep(睡眠)、suspend(掛起)等方法,失去所佔有的資源之後,該線程就從運行狀態進入阻塞狀態。
    等待阻塞:運行狀態中的線程執行wait()方法,使線程進入等待阻塞狀態。
    同步阻塞:線程在獲取sychronized同步鎖失敗。
    其他阻塞:通過調用線程的sleep()或者join()發出了I/O請求,線程就進入了阻塞狀態。
    死亡狀態:~~~~~~~

  2. 創建一個線程的方法:
    繼承Thread類
    實現Runnable接口
    實現Callable接口與Future結合

  3. 推薦創建單線程的時候使用繼承Thread方式創建,創建多線程的時候使用Runnable、Callable接口來創建。
    ·繼承Thread類創建的線程,可以直接使用Thread類中的方法,比如使用sleep方法,而不必在前面加上一個Thread。
    使用Thread類的侷限性:資源不能共享,無法放入線程池中等。
    ·使用Runnable、Callable接口的方式創建線程,可以實現資源共享,增強代碼的複用性,並且可以避免單繼承的侷限性,可以和線程池完美結合。

  4. yield():表示暫停當前正在執行的線程,並執行其他線程。只是使當前線程回到可執行狀態,有可能進入可執行狀態後馬上又被執行
    sleep():使當前線程進入停滯狀態,所以執行sleep()的線程在指定的時間內肯定不會被執行。

  5. join(): 等待某個線程終止,才執行後面的代碼。

  6. 線程的優先級:setPriority()設置線程的優先級
    Thread,MIN_PRIORITY(最低優先級、取值爲1)
    Thread,MAX_PRIORITY(最高優先級、取值爲10)
    Thread,NORM_PRIORITY(默認優先級、取值爲5)

  7. 線程中常用的方法:
    sleep():在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行);不會釋放對象鎖。
    join():只等待t線程終止。
    yield():暫停當前正在執行的線程對象,並執行其他線程。
    setPriority():設置一個線程的優先級。
    interrupt():調用當前線程的interrupt方法,可以打斷阻塞。
    wait():強迫一個線程等待。它是一個Object的方法。wait方法會釋放對象鎖,讓其他線程可以訪問。
    isAlive():判斷一個線程是否存活。
    activeCount():程序中活躍的線程數。
    currentThread():得到當前線程。
    setDaemon():設置一個線程爲守護線程(用戶線程和守護線程的區別在於,是否等待主線程依賴於主線程結束而結束)。
    setName():爲線程設置一個名稱。
    notify():通知一個線程繼續運行,也是一個Object方法,通常和wait方法一起使用。

  8. sleep()和wait()區別:
    ·使用sleep方法可以讓當前線程休眠,時間一到當前線程繼續往下執行,在任何地方都能使用,但需要捕獲InterruptedException異常。
    ·使用wait方法則必須放在synchronized塊裏面,同樣需要捕獲InterruptedException異常,並且需要獲取對象的鎖。
    ·wait方法還需要額外的方法notify/notifyAll進行喚醒,它們同樣需要放在synchronized塊裏面,且需要獲取對象的鎖。
    使用場景:sleep一般對於當前線程休眠,或者輪循暫停操作,wait則多用於多線程之間的通信。
    ·sleep是Thread類的靜態本地方法,wait則是Object類的本地方法。
    ·sleep會讓出CPU執行時間且強制上下文切換,而wait則不一定,wait後可能還有機會重新競爭到鎖繼續執行。

  9. 並行:多個CPU實例或者多臺機器同時執行一段處理邏輯,是真正的同時。
    併發:通過cpu調度算法。讓用戶看上去同時執行,實際上從cpu操作層面不是真正的同時。

  10. 繼承Thread類的方法實現線程安全 static方法

  11. 兩個線程同時訪問一個對象的相同的synchronized方法
    同一實例擁有同一把鎖,其他線程必然等待,順序執行

  12. 兩個線程同時訪問兩個對象的相同的synchronized方法
    不同的實例擁有的鎖是不同的,所以不影響,並行執行

  13. 兩個線程同時訪問兩個對象的相同的static的synchronized方法
    靜態同步方法,是類鎖,所有實例是同一把鎖,其他線程必然等待,順序執行

  14. 兩個線程同時訪問同一對象的synchronized方法與非synchronized方法
    非synchronized方法不受影響,並行執行

  15. 兩個線程訪問同一對象的不同的synchronized方法
    同一實例擁有同一把鎖,所以順序執行(說明:鎖的是this對象==同一把鎖)

  16. 兩個線程同時訪問同一對象的static的synchronized方法與非static的synchronized方法
    static同步方法是類鎖,非static是對象鎖,原理上是不同的鎖,所以不受影響,並行執行

  17. 方法拋出異常後,會釋放鎖嗎
    會自動釋放鎖,這裏區別Lock,Lock需要顯示的釋放鎖

  18. 重寫Thread類的run方法和實現Runnable接口的run方法還有一個很重要的不同,Thread類的run方法不能共享,
    而使用Runnable接口實現實現這一點。使用同一個Runnable的實例構造不同的Thread實例。

  19. 一個線程的創建肯定是由另一個線程完成的。 被創建的線程的父線程是創建他的線程。

  20. main線程所在的ThreadGroup稱爲main;構造一個線程的時候如果沒有顯式地指定ThreadGroup,name它將會和父線程同屬於一個ThreadGroup

  21. 使用TimeUnit代替Thread.sleep
    枚舉類TimeUnit對sleep方法提供了封裝,可以省去單位換算步驟
    線程休眠3小時24分鐘14秒33毫秒可以表示爲:
    TimeUnit.HOURS.sleep(3)
    TimeUnit.MINUTES.sleep(24)
    TimeUnit.SECONDS.sleep(14)
    TimeUnit.MILLISECONDS.sleep(33)

  22. synchronized注意點:
    ·與monitor關聯的對象不能爲空
    ·synchronized作用域太大,由於synchronized關鍵字存在排他新,也就是說所有的線程必須串行的經過synchronized保護的共享區域
    如果synchronized作用域越大,則代表着其效率越低,甚至還會喪失併發的優勢。
    ·this Monitor 對於同一實例有影響
    ·class Monitor與static synchronized 作用一樣 都是類鎖,對整個類有影響。

  23. 同步代碼的monitor必須與執行wait notify方法的對象一致,簡單地說就是用哪個對象的monitor進行同步,就只能用哪個對象進行wait和notify操作。

  24. Java通過Executors提供四種線程池,分別爲:
    newCachedThreadPool創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程,若無可回收,則新建線程。
    newFixedThreadPool 創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
    newScheduledThreadPool 創建一個定長線程池,支持定時及週期性任務執行。
    newSingleThreadExecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。

  25. RejectedExcecutionHandler線城市四種拒絕任務策略:
    DiscardPolicy 直接丟棄
    DiscardOldestPolicy 丟棄隊列中最老的任務
    AbortPolicy 拋異常
    CallerRunsPolicy 將任務分配給調用線程來執行

  26. 關閉線程池的兩個方法:
    shutdown:線程池拒絕接受新提交的任務,同時立馬關閉線程池,線程池裏的任務不再執行。
    shutdownNow: 線程池拒絕接收新提交的任務,同時立馬關閉線程池,線程池裏的任務不再執行。

  27. 餓漢式單例模式在多線程下可以保證只有一個實例,但是不能實現懶加載;
    懶漢式單例模式在多線程下不能保證只有一個實例,但是可以採用在getInstance方法前加上static synchronized同步約束。 性能比較低下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章