线程池 迷南。 2022-06-06 11:47 39阅读 0赞 一、ThreadPoolExecutor public class ThreadPoolExecutor extends AbstractExecutorService 所有已实现的接口: Executor, ExecutorService 一个 [ `ExecutorService`][_ExecutorService],它使用可能的几个池线程之一执行每个提交的任务,通常使用 [ `Executors`][_Executors] 工厂方法配置。 线程池可以解决两个不同问题:由于减少了每个任务调用的开销,它们通常可以在执行大量异步任务时提供增强的性能,并且还可以提供绑定和管理资源(包括执行任务集时使用的线程)的方法。每个ThreadPoolExecutor 还维护着一些基本的统计数据,如完成的任务数。 为了便于跨大量上下文使用,此类提供了很多可调整的参数和扩展钩子 (hook)。但是,强烈建议程序员使用较为方便的 [ `Executors`][_Executors] 工厂方法 [ `Executors.newCachedThreadPool()`][_Executors.newCachedThreadPool](无界线程池,可以进行自动线程回收)、[`Executors.newFixedThreadPool(int)`][Executors.newFixedThreadPool_int](固定大小线程池)和[`Executors.newSingleThreadExecutor()`][Executors.newSingleThreadExecutor](单个后台线程),它们均为大多数使用场景预定义了设置。否则,在手动配置和调整此类时,使用以下指导: 核心和最大池大小 ThreadPoolExecutor 将根据 corePoolSize(参见 [ `getCorePoolSize()`][_getCorePoolSize])和 maximumPoolSize(参见 [ `getMaximumPoolSize()`][_getMaximumPoolSize])设置的边界自动调整池大小。当新任务在方法 [ `execute(java.lang.Runnable)`][_execute_java.lang.Runnable] 中提交时,如果运行的线程少于 corePoolSize,则创建新线程来处理请求,即使其他辅助线程是空闲的。如果运行的线程多于 corePoolSize 而少于 maximumPoolSize,则仅当队列满时才创建新线程。如果设置的 corePoolSize 和 maximumPoolSize 相同,则创建了固定大小的线程池。如果将 maximumPoolSize 设置为基本的无界值(如 Integer.MAX\_VALUE),则允许池适应任意数量的并发任务。在大多数情况下,核心和最大池大小仅基于构造来设置,不过也可以使用 [ `setCorePoolSize(int)`][_setCorePoolSize_int] 和 [ `setMaximumPoolSize(int)`][_setMaximumPoolSize_int] 进行动态更改。 按需构造 默认情况下,即使核心线程最初只是在新任务到达时才创建和启动的,也可以使用方法 [ `prestartCoreThread()`][_prestartCoreThread] 或 [ `prestartAllCoreThreads()`][_prestartAllCoreThreads] 对其进行动态重写。如果构造带有非空队列的池,则可能希望预先启动线程。 创建新线程 使用 [ `ThreadFactory`][_ThreadFactory] 创建新线程。如果没有另外说明,则在同一个 [ `ThreadGroup`][_ThreadGroup] 中一律使用 [ `Executors.defaultThreadFactory()`][_Executors.defaultThreadFactory] 创建线程,并且这些线程具有相同的 NORM\_PRIORITY 优先级和非守护进程状态。通过提供不同的 ThreadFactory,可以改变线程的名称、线程组、优先级、守护进程状态,等等。如果从 newThread 返回 null 时 ThreadFactory 未能创建线程,则执行程序将继续运行,但不能执行任何任务。 保持活动时间 如果池中当前有多于 corePoolSize 的线程,则这些多出的线程在空闲时间超过 keepAliveTime 时将会终止(参见 [ `getKeepAliveTime(java.util.concurrent.TimeUnit)`][_getKeepAliveTime_java.util.concurrent.TimeUnit])。这提供了当池处于非活动状态时减少资源消耗的方法。如果池后来变得更为活动,则可以创建新的线程。也可以使用方法 [`setKeepAliveTime(long, java.util.concurrent.TimeUnit)`][setKeepAliveTime_long_ java.util.concurrent.TimeUnit] 动态地更改此参数。使用 Long.MAX\_VALUE [ `TimeUnit.NANOSECONDS`][_TimeUnit.NANOSECONDS] 的值在关闭前有效地从以前的终止状态禁用空闲线程。默认情况下,保持活动策略只在有多于 corePoolSizeThreads 的线程时应用。但是只要 keepAliveTime 值非 0, [`allowCoreThreadTimeOut(boolean)`][allowCoreThreadTimeOut_boolean] 方法也可将此超时策略应用于核心线程。 排队 所有 [ `BlockingQueue`][_BlockingQueue] 都可用于传输和保持提交的任务。可以使用此队列与池大小进行交互: * 如果运行的线程少于 corePoolSize,则 Executor 始终首选添加新的线程,而不进行排队。 * 如果运行的线程等于或多于 corePoolSize,则 Executor 始终首选将请求加入队列,而不添加新的线程。 * 如果无法将请求加入队列,则创建新的线程,除非创建此线程超出 maximumPoolSize,在这种情况下,任务将被拒绝。 排队有三种通用策略: 1. *直接提交。*工作队列的默认选项是 [ `SynchronousQueue`][_SynchronousQueue],它将任务直接提交给线程而不保持它们。在此,如果不存在可用于立即运行任务的线程,则试图把任务加入队列将失败,因此会构造一个新的线程。此策略可以避免在处理可能具有内部依赖性的请求集时出现锁。直接提交通常要求无界 maximumPoolSizes 以避免拒绝新提交的任务。当命令以超过队列所能处理的平均数连续到达时,此策略允许无界线程具有增长的可能性。 2. *无界队列。*使用无界队列(例如,不具有预定义容量的 [ `LinkedBlockingQueue`][_LinkedBlockingQueue])将导致在所有 corePoolSize 线程都忙时新任务在队列中等待。这样,创建的线程就不会超过 corePoolSize。(因此,maximumPoolSize 的值也就无效了。)当每个任务完全独立于其他任务,即任务执行互不影响时,适合于使用无界队列;例如,在 Web 页服务器中。这种排队可用于处理瞬态突发请求,当命令以超过队列所能处理的平均数连续到达时,此策略允许无界线程具有增长的可能性。 3. *有界队列。*当使用有限的 maximumPoolSizes 时,有界队列(如 [ `ArrayBlockingQueue`][_ArrayBlockingQueue])有助于防止资源耗尽,但是可能较难调整和控制。队列大小和最大池大小可能需要相互折衷:使用大型队列和小型池可以最大限度地降低 CPU 使用率、操作系统资源和上下文切换开销,但是可能导致人工降低吞吐量。如果任务频繁阻塞(例如,如果它们是 I/O 边界),则系统可能为超过您许可的更多线程安排时间。使用小型队列通常要求较大的池大小,CPU 使用率较高,但是可能遇到不可接受的调度开销,这样也会降低吞吐量。 被拒绝的任务 当 Executor 已经关闭,并且 Executor 将有限边界用于最大线程和工作队列容量,且已经饱和时,在方法 [ `execute(java.lang.Runnable)`][_execute_java.lang.Runnable] 中提交的新任务将被 *拒绝*。在以上两种情况下, execute 方法都将调用其 [ `RejectedExecutionHandler`][_RejectedExecutionHandler] 的 [ `RejectedExecutionHandler.rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor)`][_RejectedExecutionHandler.rejectedExecution_java.lang.Runnable_ java.util.concurrent.ThreadPoolExecutor] 方法。下面提供了四种预定义的处理程序策略: 1. 在默认的 [ `ThreadPoolExecutor.AbortPolicy`][_ThreadPoolExecutor.AbortPolicy] 中,处理程序遭到拒绝将抛出运行时 [ `RejectedExecutionException`][_RejectedExecutionException]。 2. 在 [ `ThreadPoolExecutor.CallerRunsPolicy`][_ThreadPoolExecutor.CallerRunsPolicy] 中,线程调用运行该任务的 execute 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。 3. 在 [ `ThreadPoolExecutor.DiscardPolicy`][_ThreadPoolExecutor.DiscardPolicy] 中,不能执行的任务将被删除。 4. 在 [ `ThreadPoolExecutor.DiscardOldestPolicy`][_ThreadPoolExecutor.DiscardOldestPolicy] 中,如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)。 定义和使用其他种类的 [ `RejectedExecutionHandler`][_RejectedExecutionHandler] 类也是可能的,但这样做需要非常小心,尤其是当策略仅用于特定容量或排队策略时。 钩子 (hook) 方法 此类提供 protected 可重写的 [ `beforeExecute(java.lang.Thread, java.lang.Runnable)`][_beforeExecute_java.lang.Thread_ java.lang.Runnable] 和 [ `afterExecute(java.lang.Runnable, java.lang.Throwable)`][_afterExecute_java.lang.Runnable_ java.lang.Throwable] 方法,这两种方法分别在执行每个任务之前和之后调用。它们可用于操纵执行环境;例如,重新初始化 ThreadLocal、搜集统计信息或添加日志条目。此外,还可以重写方法 [`terminated()`][terminated] 来执行 Executor 完全终止后需要完成的所有特殊处理。 如果钩子 (hook) 或回调方法抛出异常,则内部辅助线程将依次失败并突然终止。 队列维护 方法 [ `getQueue()`][_getQueue] 允许出于监控和调试目的而访问工作队列。强烈反对出于其他任何目的而使用此方法。 [ `remove(java.lang.Runnable)`][_remove_java.lang.Runnable] 和 [ `purge()`][_purge] 这两种方法可用于在取消大量已排队任务时帮助进行存储回收。 终止 程序 *AND* 不再引用的池没有剩余线程会自动 shutdown。如果希望确保回收取消引用的池(即使用户忘记调用 [ `shutdown()`][_shutdown]),则必须安排未使用的线程最终终止:设置适当保持活动时间,使用 0 核心线程的下边界和/或设置 [ `allowCoreThreadTimeOut(boolean)`][allowCoreThreadTimeOut_boolean]。 # Spring线程池ThreadPoolTaskExecutor配置及详情 # <!-- spring thread pool executor --> <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <!-- 线程池维护线程的最少数量 --> <property name="corePoolSize" value="5" /> <!-- 允许的空闲时间 --> <property name="keepAliveSeconds" value="200" /> <!-- 线程池维护线程的最大数量 --> <property name="maxPoolSize" value="10" /> <!-- 缓存队列 --> <property name="queueCapacity" value="20" /> <!-- 对拒绝task的处理策略 --> <property name="rejectedExecutionHandler"> <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" /> </property> </bean> 属性字段说明 corePoolSize:线程池维护线程的最少数量 keepAliveSeconds:允许的空闲时间 maxPoolSize:线程池维护线程的最大数量 queueCapacity:缓存队列 rejectedExecutionHandler:对拒绝task的处理策略 ## 2. execute(Runable)方法执行过程 ## 如果此时线程池中的数量**小于**corePoolSize,即使线程池中的线程都处于空闲状态,也要**创建新**的线程来处理被添加的任务。 如果此时线程池中的数量**等于** corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。 如果此时线程池中的数量**大于**corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maxPoolSize,建新的线程来处理被添加的任务。 如果此时线程池中的数量**大于**corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maxPoolSize,那么通过handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。 当线程池中的线程数量**大于**corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。 [_ExecutorService]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ExecutorService.html [_Executors]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/Executors.html [_Executors.newCachedThreadPool]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/Executors.html#newCachedThreadPool%28%29 [Executors.newFixedThreadPool_int]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/Executors.html#newFixedThreadPool%28int%29 [Executors.newSingleThreadExecutor]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/Executors.html#newSingleThreadExecutor%28%29 [_getCorePoolSize]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#getCorePoolSize%28%29 [_getMaximumPoolSize]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#getMaximumPoolSize%28%29 [_execute_java.lang.Runnable]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#execute%28java.lang.Runnable%29 [_setCorePoolSize_int]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#setCorePoolSize%28int%29 [_setMaximumPoolSize_int]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#setMaximumPoolSize%28int%29 [_prestartCoreThread]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#prestartCoreThread%28%29 [_prestartAllCoreThreads]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#prestartAllCoreThreads%28%29 [_ThreadFactory]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadFactory.html [_ThreadGroup]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/lang/ThreadGroup.html [_Executors.defaultThreadFactory]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/Executors.html#defaultThreadFactory%28%29 [_getKeepAliveTime_java.util.concurrent.TimeUnit]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#getKeepAliveTime%28java.util.concurrent.TimeUnit%29 [setKeepAliveTime_long_ java.util.concurrent.TimeUnit]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#setKeepAliveTime%28long,%20java.util.concurrent.TimeUnit%29 [_TimeUnit.NANOSECONDS]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/TimeUnit.html#NANOSECONDS [allowCoreThreadTimeOut_boolean]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#allowCoreThreadTimeOut%28boolean%29 [_BlockingQueue]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/BlockingQueue.html [_SynchronousQueue]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/SynchronousQueue.html [_LinkedBlockingQueue]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/LinkedBlockingQueue.html [_ArrayBlockingQueue]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ArrayBlockingQueue.html [_RejectedExecutionHandler]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/RejectedExecutionHandler.html [_RejectedExecutionHandler.rejectedExecution_java.lang.Runnable_ java.util.concurrent.ThreadPoolExecutor]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/RejectedExecutionHandler.html#rejectedExecution%28java.lang.Runnable,%20java.util.concurrent.ThreadPoolExecutor%29 [_ThreadPoolExecutor.AbortPolicy]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.AbortPolicy.html [_RejectedExecutionException]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/RejectedExecutionException.html [_ThreadPoolExecutor.CallerRunsPolicy]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.CallerRunsPolicy.html [_ThreadPoolExecutor.DiscardPolicy]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.DiscardPolicy.html [_ThreadPoolExecutor.DiscardOldestPolicy]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.DiscardOldestPolicy.html [_beforeExecute_java.lang.Thread_ java.lang.Runnable]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#beforeExecute%28java.lang.Thread,%20java.lang.Runnable%29 [_afterExecute_java.lang.Runnable_ java.lang.Throwable]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#afterExecute%28java.lang.Runnable,%20java.lang.Throwable%29 [terminated]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#terminated%28%29 [_getQueue]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#getQueue%28%29 [_remove_java.lang.Runnable]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#remove%28java.lang.Runnable%29 [_purge]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#purge%28%29 [_shutdown]: http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html#shutdown%28%29
相关 Java 线程池、Runnable线程池、Callable线程池 线程池: 其实就是一个容纳多个线程的容器,其中的线程可以反复的使用,省去了频繁创建和销毁过程对象的操作,无需反复创建线程面消耗过多资源。 为什么要用线程池: 合理 青旅半醒/ 2023年02月26日 12:30/ 0 赞/ 52 阅读
相关 线程、线程池 创建线程的3种方法: package com.frank.threadPool.createThread; / @author 小石潭记 布满荆棘的人生/ 2022年10月22日 04:27/ 0 赞/ 385 阅读
相关 线程池 1.所谓线程池,就是程序的初始化阶段,就预先创建一批线程,每个线程都做好准备干活; 2.然后有一个任务列表,一开始为空,当有任务来了,就往任务列表里面添加;这个任务列表 痛定思痛。/ 2022年06月13日 13:22/ 0 赞/ 329 阅读
相关 线程池 西施越溪女,明艳光云海 最近用线程池和不用线程池做了个速度的测试,在这里备注下: 结果是速度不相上下; public static void main(Str 妖狐艹你老母/ 2022年05月20日 02:35/ 0 赞/ 283 阅读
相关 线程池 线程池 Java里面线程池的顶级接口是 java.util.concurrent.Executor , 但是严格意义上讲 Executor并不是一个线程池,而只是一个 迈不过友情╰/ 2022年03月06日 14:34/ 0 赞/ 401 阅读
相关 线程池 线程池 > 从字面义上来讲,是指管理一组同构工作线程的资源池。线程池是与工作队列密切相关的,其中在工作队列中(Worker Queue)保存了所有等待执行的任务。工作者( 清疚/ 2021年12月11日 03:35/ 0 赞/ 388 阅读
相关 线程池 可preStart一个或全部core thread 0,小于core则来一个任务建一个线程(firstTask),队列,额外线程,拒绝 一个AtomicInteger的 今天药忘吃喽~/ 2021年11月23日 03:40/ 0 赞/ 412 阅读
相关 线程池 1、先创建线程池 import java.util.concurrent.ArrayBlockingQueue; import java.util.concu 拼搏现实的明天。/ 2021年11月09日 14:28/ 0 赞/ 422 阅读
还没有评论,来说两句吧...