java线程池工作原理面试题(Java 线程池之Jetty 线程池学习总结)
Java 线程池之Jetty 线程池学习总结
前提
Jetty 11.0.x
为什么是Jetty?
Java提供4中创建线程池的快捷方式
Executors.newFixedThreadPool(); Executors.newCachedThreadPool(); Executors.newSingleThreadExecutor(); Executors.newScheduledThreadPool();但通常我们很少用这4个工厂方法去创建线程池 ,而是直接使用ThreadPoolExecutor类构造线程池 ,因为这些工厂方法最终也是调用这个类来创建线程池的 。
众所周知 ,虽然ThreadPoolExecutor提供了corePoolSize和maximumPoolSize两个参数来控制线程池的基本大小和最大大小 ,但是这两个参数并不是那么好用:当任务队列采用SynchronousQueue时 ,通常需要无界的maximumPoolSize;当任务队列采用无界队列时 ,maximumPoolSize的值又相当于不起作用;当任务队列采用有界队列时 ,仅在任务队列已满 ,且未达到maximumPoolSize时才会扩充线程池大小 。
既然如此 ,那有没有一种更简单的实现方案呢?使用该方案 ,使用者只需要简单的配置下线程池的基本大小和最大大小 ,程序就可以根据任务的繁忙程度自动调整当前线程数量 。答案是有的:Jetty--一个基于Java的web容器 ,和Tomcat齐名
Jetty线程池介绍
任务处理流程
初始化线程池
程序初始化运行时,会先创建线程池 ,线程池大小默认为minThreads ,也就是说会预先创建minThreads个线程,线程名称格式形如“qtp1076496284-13 ”
创建线程池时:
如果未指定最大线程数(maxThreads) ,则默认为 200;
如果未指定最小线程数(minThreads) ,则默认为 8
如果未指定线程空闲超时时间(idleTimeout) ,则默认为 60000 ,即60秒
保留线程数(reservedThreads)默认为 -1
如果未指定任务队列 ,则默认创建BlockingArrayQueue任务队列 ,容量大小为 8 x 1024
如果指定的最大线程数小于最小线程数 ,则抛出异常
线程池扩缩容
当前线程数比最小线程数小 ,或者没有空闲的线程 ,且当前线程数(threads )小于最大线程数 ,则创建线程; idleTimout大于0且当前线程数大于最小线程数 ,且线程空闲时间超过idleTimeout ,则停止线程注意:程序判断是否存在空闲线程的逻辑是这样的:Net空闲线程数 = 空闲线程数 - 任务队列大小,如果“Net空闲线程数 ”为负数 ,则表示不存在空闲线程 ,即需要更多的线程来处理任务 。
任务队列及线程相关定义
queueSize 任务队列大小,即队列中等待被线程执行的任务数 。可通过getQueueSize()函数获取 。
threads 当前线程池中的线程数 ,包括已租给内部组件的线程 、空闲线程 、保留线程 ,以及正在执行临时作业的线程 。threads = readyThreads + leasedThreads + utilizedThreads 。 可通过getThreads() 函数获取 。
readyThreads 准备执行临时任务的线程数 。readyThreads = idleThreads + availableReservedThreads 。可通过getReadyThreads()函数获取 。
idleThreads 未被保留的空闲线程数。idleThreads = readyThreads - availableReservedThreads 。可通过getIdleThreads()函数获取 。
reservedThreads 保留的线程数 ,默认值为-1。可通过getReservedThreads()函数获取 。
availableReservedThreads 可用的保留线程 。可通过getAvailableReservedThreads()函数获取 。
leasedThreads 供内部组件使用 ,用于执行内部任务的线程 。需要线程的Jetty组件(比如网络acceptors和selector)可能会使用ThreadPoolBudget从线程池中租用线程 。站在线程池的角度来看 ,这些被租用的线程是活跃的 ,但是不能用于执行临时任务 ,比如一个HTTP请求 ,或者一个WebSocket帧 。QueuedThreadPool有一个ReservedThreadExecutor ,该组件会从线程池租用线程 ,但会让这些线程可用 ,就像它们是“idle ”线程一样 。线程池启动后 ,该值一般是恒定的 。可通过getLeasedThreads()函数获取 。
minThreads 线程池中的最小线程数 。可通过getMinThreads() 函数获取 。
maxThreads 线程池中的最大线程数 。可通过getMaxThreads() 函数获取。
maxAvailableThreads 可用于执行临时任务的最大线程数 。maxAvailableThreads = maxThreads - leasedThreads 可通过getMaxAvailableThreads()函数获取 。
utilizedThreads执行临时任务的线程数,可通过getUtilizedThreads()函数获取。utilizedThreads = threads - leasedThreads - readyThreads
utilizationRate = utilizedThreads / maxAvailableThreads 执行临时任务的线程利用率 。该值为0.0D则表示线程池未被利用 ,如果为1.0D则表示线程池被充分利用于执行临时任务 。可通过getUtilizationRate() 函数获取 。
busyThreads 正在执行内部任务和临时任务的线程数 。 busyThreads = utilizedThreads + leasedThreads 。可通过getBusyThreads()函数获取 。
参考链接
https://www.eclipse.org/jetty/javadoc/jetty-11/org/eclipse/jetty/util/thread/QueuedThreadPool.html
https://gitee.com/Tedgar156/jetty.project/blob/jetty-11.0.x/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!