threadPool注解直译
# threadPool注解直译
翻译:
核心和最大线程数Core and maximum pool sizes
线程池执行器会根据corePoolSize和maximumPoolSize设置的界限自动调节池子大小。当一个新的任务被提交时,并且正在运行的线程数小于corePoolSize,即使其它线程都是空闲的,也会创建一个新的线程来执行该任务。如果正大运行的线程数大于corePoolSize且小于maximumPoolSize时,只有当队列满的时候才会创建新的线程。如果corePoolSize和maximumPoolSize设置一样,相当于创建了一个fixed-size固定大小的线程池。如果maximumPoolSize设置足够大如Integer.MAX_VALUE,相当于允许容纳任意数量的并发任务。一般来讲,corePoolSize和maximumPoolSize只能基于构造方法来设置(不会翻译,应该是这个意思。)但是它们也有可能会使用setCorePoolSize和setMaximumPoolSize方法来动态调整。
请求式结构On-demand construction
默认的,核心线程只能在新的任务到达的时候才会被初始创建,但是这可以使用prestartCoreThread或prestartAllCoreThreads方法动态的覆盖。如果你构造一个非空队列的线程池时你可以想提前启动线程。
创建新的线程Creating new threads
使用java.util.concurrent.ThreadFactory来创建新的线程,如果没有其它的指定,将会使用java.util.concurrent.Executors.defaultThreadFactory(),创建的线程都会在相同的线程组中,并且相同的默认优先级和非守护进程状态。根据提供的不同的线程工厂,可以修改线程名称,线程组,优先级,守护进程状态等。如果ThreadFactory的newThread返回null创建线程失败,执行器也会继续但是可能不会执行任何任务。线程应该持有修改线程的运行时权限,如果没有权限,服务可能会降级:配置变化可以及时生效,关闭的池子可能保留在终止可以已经发生但没有完全终止的状态。
保持存活的时间Keep-alive times
如果池子当前有超过corePoolSize的线程数量,超过数量且过了存活时间且空闲的线程将会被终止,这里提出了一个当池子没有被频繁使用时降低资源消耗的思想。如果过了一会池子又变得使用频繁了,新的线程就会被重新构造。这个参数也可以使用setKeepAliveTime来动态的调整。MAX_VALUE TimeUnit.NANOSECONDS 可以有效的禁止始终优先关闭的线程关闭。默认情况下存活策略仅适用当线程数超过corePoolSize的情况,但是allowCoreThreadTimeOut方法同样也可以适用核心线程的超时策略,只要keepAliveTime的值不为0。
排队Queuing
任何阻塞队列都可能会被用来转存和持有提交的任务,队列与池子大小的交互的作用:
- 如果小于corePoolSize数量的线程正在运行,执行器会始终添加新的线程而不是排队处理。
- 如果大于等于corePoolSize数量的线程正在运行,执行器会始终会把新的请求加入队列而不是创建新的线程。
- 如果新到达的请求不能被加入队列,队列满了,将会创建新的线程,除非当前线程数超过了maximumPoolSize,这种情况下,新的请求将会被拒绝。
这里有三种常规的排队策略
- 直接传递。对于一个工作队列来讲,一种好的默认选择就是SynchronousQueue同步队列,它直接把任务交给线程而不持有它们。在这种情况下,尝试往队列里加一个任务会失败,如果没有线程立刻可用来运行它,所以一个新线程将会被创建,当处理一系列可能存在内部依赖的任务时,这个策略避免了阻塞。直接递交策略一般要求无界最大线程数来避免新任务的提交。这就导致了,当任务到达的速度比任务处理的速度更快时,线程可能会无限增长。
- 无界队列。使用无界队列(例如LinkedBlockingQueue),当所有核心线程都忙时,会导致新提交的任务在队列中等待。这样,就不会有多于核心线程数的线程被创建。(这样,最大线程数的值就没有任何影响了)当每个任务都独立于其他任务时,这种状况也许比较合适,这样任务不能影响到其他任务的执行,举个例子,在一个网页服务器上。在这种风格可以对快速到来的请求起到消峰的作用的同时,当任务到达的速度比任务处理的速度更快时,线程可能会无限增长。
- 有界队列。当使用有限最大线程数时,一个有界队列(例如ArrayBlockingQueue)可以帮助阻止资源过度消耗,但是却更不容易协调和控制。队列大小和线程池大小有可能是彼此的折中:使用大的队列和小的线程池大小能够降低CPU消耗,操作系统资源,和上下文环境切换负载,但是却能导致很低的吞吐量。如果任务频繁被阻塞(例如他们被io阻塞),系统就可以调度比你允许的更多的线程。使用小的队列一般要求同时使用大的线程池,这样可以使CPU保持忙碌但是可能导致无法接受的调度负载,这同样会降低吞吐量。