Java - JVM - 線程時間片的其他操作


  1. 概述

    1. Java 線程偏向於 時間片 的操作
  2. 背景

    1. 之前了解 圍繞監視器鎖 的一些線程操作

      1. synchronized
      2. wait(), notify(), notifyAll()
    2. 但是還有別的問題, 沒有覆蓋到

    3. 問題

      1. 我想讓我的線程 在不釋放鎖 的情況下, 停止一段時間
      2. 我想讓我的線程, 放棄現在的 時間片
      3. 我想讓我的線程, 排在別的線程之后
    4. 這些問題, 光靠 監視器鎖, 好像解決不了

      1. 沒關系, 我們還有別的工具

1. 睡眠

  1. 概述

    1. 線程暫停
  2. 場景: 輪詢

    1. 問題
      1. 線程輪詢時, 如果一直高頻率詢問, 會有弊端

        1. 高頻詢問消耗 cpu 資源
        2. 高頻詢問, 很多次詢問, 都是無效的
      2. 解決

        1. 一次輪詢失敗后, 休息一段時間, 再嘗試下一次輪詢
  3. sleep()

    1. 概述

      1. 讓當前線程, 停止一段時間, 然后繼續
    2. 解釋

      1. 當前線程

        1. 只能給 當前線程 使用
          1. 源碼注釋
        2. static 方法
      2. 停止

        1. 具體機制
          1. 將當前線程轉換到 wait 狀態
            1. 線程狀態?
              1. 不執行任何代碼
              2. 消耗最少的資源
              3. 等待 調度器 喚醒
      3. 一段時間

        1. 單位
          1. ms
        2. 定義
          1. 時間是由 調用者 設定的
      4. 繼續

        1. 繼續上次的執行
          1. 從 sleep 下一句開始
  4. 問題

    1. sleep 的時間, 可能會不准確
      1. 狀態

        1. sleep 被喚醒后, 是 可執行狀態
        2. 可執行 到 執行中, 會有一個 時間
      2. 線程調度

        1. sleep 從 wait 到 被喚醒, 到 分配到時間片執行, 中間需要若干個 線程調度 的步驟
        2. 不同的 jvm 實現, 可能會有所差異
      3. 誤差

        1. 誤差通常在 10ms 左右吧
  5. 注意

    1. sleep 不會對鎖有影響

      1. 可以在 同步/非同步 代碼里執行
      2. sleep 不會改變鎖的 持有情況
    2. sleep 如果被打斷, 會拋出異常

      1. InterruptedException
      2. 這個后續再說

2. 讓步

  1. 概述

    1. 讓步
  2. 場景: ...

    1. 尷尬了
      1. 老實說, 我也不知道這有什么場景
      2. 源碼里提到, 這個方法在 java.util.concurrent.locks 的代碼測試中有過使用
    2. 作用
      1. 收回當前線程的 時間片, 讓線程重新回到 runable 階段
      2. 重新開展 線程調度
  3. yield()

    1. 概述

      1. 讓當前線程, 讓出 cpu 時間片
    2. 解釋

      1. 當前線程

        1. 同 sleep
      2. 讓出 cpu 世間片

        1. 線程的執行, 需要 cpu時間片
        2. 讓出 cpu時間片, 則 線程不再執行
        3. 通常線程會回到 runable 階段, 重新參與調度
  4. 注意

    1. 可能會被部分 jvm 忽略
    2. yield 不會對鎖 有影響
      1. 同 sleep

3. 合成

  1. 概述

    1. 合成
  2. 場景: 先后執行

    1. 先后執行

      1. 線程T1 需要等待 線程T2 的執行結果
      2. 線程T1 持有 線程T2 的引用
    2. 疑問

      1. 為啥不用 監視器鎖
        1. 有些代碼實現, 沒有用 synchronized, 我想等這塊的東西, 但又不想改代碼
  3. join()

    1. 概述

      1. 等待其他線程執行結束, 然后繼續
    2. 解釋

      1. 等待

        1. 保持 wait 狀態
          1. 持續執行 wait 方法
        2. 機制
          1. T1 執行 T2 的 join 方法
            1. 帶時間參數的 join, 竟然是 同步方法
          2. T1 獲得 T2 的 鎖
            1. 沒錯, 是 線程T2 對應 Thread 對象的鎖
            2. 這個 通常 不會影響 T2 正在執行的任務
            3. 但是如果真的被阻塞了, 確實需要等在那里
          3. T1 開始循環, 判斷 T2 是否存活
            1. 如果 T2 存活, 則一直 wait()
              1. wait() 就意味着鎖...
      2. 其他線程

        1. join 需要持有其他線程的引用
      3. 繼續

        1. join 回來后, 從 wait 后面的代碼開始, 繼續執行
  4. 問題: 抱歉, 這倆問題, 我現在無法解答

    1. T1 在 wait 階段, T2 還活着, T1 是怎么被喚醒的

    2. 同步方法是不是意味着, 只能有一個 T2 的 join, 只能被一個線程調用

      1. 如果多個線程調用 wait, 會是怎樣一種請情況
    3. T2 線程如果出現了異常, T1 會是怎么樣一種反應?

  5. 注意

    1. join 途中, 如果被打斷, T1 會拋出異常
      1. InterruptedException
        1. 怎么又是你

4. 后續

  1. 線程狀態

    1. 說了這么線程相關的方法, 終於該說這個線程狀態了
      1. 之前想嘗試先講狀態, 但是寫了點發現越寫越難寫
  2. Java 內存模型

    1. Java 內存模型, 其實很復雜
  3. 多線程

    1. 終於到這一步了...

ps

  1. ref
    1. Java 語言規范(SE 8th)
    2. Java Thread sleep
      1. 簡單清晰
    3. Java 核心技術(10th editon) 卷1
    4. Java多線程中join方法的理解
      1. 講得挺好
      2. 作者后來還成了 攜程某部門的 CTO, 還創立了 優知學院, 挺厲害的
        1. 分布式架構詳解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM