jetty线程池的实现

线程池的基本概念

  • _threadsStarted:启动的线程数
  • _threadsIdle:空闲的线程数
  • _lastShrink:记录上次线程结束时间,用于销毁空闲线程
  • _threads:使用ConcurrentLinkedQueue来存放线程
  • _joinLock:等待线程池结束的锁【不常用】
  • _jobs:默认使用BlockingArrayQueue来存放任务队列,当_maxQueued>0的时候会使用ArrayBlockingQueue(_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比如




1
3
false


会分别调用

  • 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










你可能感兴趣的:(jetty线程池的实现)