jetty線程池的實現

線程池的基本概念

  • _threadsStarted:啓動的線程數
  • _threadsIdle:空閒的線程數
  • _lastShrink:記錄上次線程結束時間,用於銷燬空閒線程
  • _threads:使用ConcurrentLinkedQueue來存放線程
  • _joinLock:等待線程池結束的鎖【不常用】
  • _jobs:默認使用BlockingArrayQueue<Runnable>來存放任務隊列,當_maxQueued>0的時候會使用ArrayBlockingQueue<Runnable>(_maxQueued)
  • _name:線程池的名字
  • _maxIdleTimeMs:線程空閒的最大時間
  • _maxThreads:最大線程數
  • _minThreads:最小線程數
  • _maxQueued:任務隊列的最大長度,默認-1(無限制即Integer.MAX_VALUE)
  • _priority:默認Thread.NORM_PRIORITY,僅在測試環境中使用setThreadsPriority(int priority)【不常用】
  •  _daemon:是否daemon線程【不常用】
  • _maxStopTime:等待線程池結束的最大時間【不常用】
  • _detailedDump:是否在調用void dump(Appendable out, String indent)是輸出更詳細的信息


線程池的常用場景

1)實例化

     根據$JETTY_HOME/etc/jetty.xml 比如     

     <Set name="ThreadPool">
      <!-- Default queued blocking threadpool -->
      <New class="org.eclipse.jetty.util.thread.QueuedThreadPool">
        <Set name="minThreads">1</Set>
        <Set name="maxThreads">3</Set>
        <Set name="detailedDump">false</Set>
      </New>
    </Set>


會分別調用    

  • setMinThreads(int minThreads)
    • 如果已啓動的線程小於最小線程數而且線程池已啓動,則開啓線程startThread(int threads)
  • setMaxThreads(int maxThreads)
  • setDetailedDump(boolean detailedDump)

此時

     線程組_threads爲空

     任務隊列_jobs爲null


2)啓動doStart()
  • _threadsStarted設置爲0
  • 實例化_jobs爲BlockingArrayQueue(默認無限制即Integer.MAX_VALUE)
  • 啓動minThreads個worker線程

3)提交dispatch(Runnable job)

  • 往jobs隊列中添加job
  • 如果添加成功,檢查如果沒有空閒線程,或者jobs中等待處理的job個數大於空閒線程  而且此時未達到最大線程數則啓動新線程

4)還有幾個不太常用的場景就不贅述了

  •  String dumpThread(long id) //dump單個線程信息
  •  boolean interruptThread(long id)//中斷線程池中某個線程
  •  void dump(Appendable out, String indent)//dump所有線程
  • void join() //等待線程池停止
  • void doStop()//停止
線程池中的線程生命週期


1)進入job循環,不斷從jobs隊列取job
2)如果取不到job退出job循環進入idle循環有一個_threadsIdle變量專門記錄worker線程進入idle循環個數
3)如果_maxIdleTimeMs<0(默認60秒),線程阻塞等待jobs中job,一旦取到再次進入job循環,到1)
4)否則檢查當前啓動線程數是否大於最小線程數,如果是且空閒時間超過_maxIdleTimeMs,則結束該線程

5)否則線程阻塞等待jobs,超時設爲_maxIdleTimeMs,如果拿到job再次進入job循環到1),否則到3)


小結

  • jetty默認線程池QueuedThreadPool實現較爲簡單
  • 沒有什麼額外的管理線程來增減線程,線程的增減在運行是自動完成,比如dispatch會添加線程,線程會根據情況自己銷燬
  • 和外界的常用接口就是dispatch和execute(會調用dispatch)
    • 也就是往jobs隊列中丟任務
    • 某些線程池比如tomcat5或者varnish會將task直接扔給線程而不是隊列,如果無空閒線程纔會扔到等待隊列
    • varnish中的線程被喚醒後會優先從等待隊列中取任務
    • jetty 線程沒有所謂的tomcat中的等待隊列的概念



注意:

  • 如果_maxQueued沒有設定即爲-1,那麼任務隊列會爲Integer.MAX_VALUE,此時是存在風險的
  • _maxIdleTimeMs並不完全是某個線程的空閒時間,很有可能某個線程還沒空閒_maxIdleTimeMs就結束掉了,因爲jetty的線程池會有一個全局的_lastShrink記錄銷燬時間,判斷是否結束的公式是now-_lastShrink>_maxIdleTimeMs,顯然更精確的公式應該是now-$(線程進入idle loop的時間)>_maxIdleTimeMs










發佈了200 篇原創文章 · 獲贊 7 · 訪問量 106萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章