线程池框架-Executor

1. 什么是线程池?

在我们程序存在并发任务时,每个任务都需要分配一个线程执行。当存在大量并发任务时,每个任务都创建一个新的线程,在任务结束时进行销毁,这种情况下,极其消耗系统的资源,线程的创建及销毁占了其生命周期的大部分时间。同时,存在突发并发任务时,容易导致降低系统的稳定性。线程池的出现,解决了这种问题。我们可以将线程的创建,管理,销毁交给线程池管理。
1.1 通过固定同一时间存在的线程数量,避免无休止创建线程导致系统资源消耗过大;
1.2 通过给新任务分配已创建的线程,减少了线程创建的时间。任务结束后,回收线程而非销毁,待新任务到来后重新分配。降低了线程的创建,销毁的花销。
1.3 通过线程池管理线程,合理配置,可以极大的提高系统运行的稳定性。

2. 线程池的Executor框架

Ps: 基于Java 8
在这里插入图片描述
在这里插入图片描述
2.1 Java 8中,Executor是一个接口,存在两个子接口ExecutorService,ScheduledExecutorService;四个实现类AbstractExecutorService,ForkJoinPool,ScheduledThreadPoolExecutor,ThreadPoolExecutor。
2.2

ExecutorService:提供了管理终止的方法,以及可以跟踪一个或多个异步任务执行状况而生成 Future 的接口。
ScheduledExecutorService:继承了ExecutorService 接口,提供延时执行或定时执行的方法。
ThreadPoolExecutor:核心实现类,通过类图,我们可以知道,ThreadPoolExecutor是对Executor的拓展,实现,增加了一下新的方法对线程池的管理。
ScheduledThreadPoolExecutor:ThreadPoolExecutor的子类,它可以额外安排命令在给定延迟后运行,或定期执行。

3. ThreadPoolExecutor
// 构造方法,使用给定的初始参数创建一个新的ThreadPoolExecutor。
ThreadPoolExecutor
				(
					int corePoolSize, 
					int maximumPoolSize, 
					long keepAliveTime, 
					TimeUnit unit, 
					BlockingQueue<Runnable> workQueue, 
					ThreadFactory threadFactory,
					RejectedExecutionHandler handler
				)

以下是各初始参数的作用介绍:
corePoolSize:线程池中保留的线程数,即使它们是空闲的,除非设置了allowCoreThreadTimeOut;
maximumPoolSize:线程池中允许的最大线程数;
keepAliveTime:当线程数大于核心数时,这是多余空闲线程在终止之前等待新任务的最大时间;
unit:keepAliveTime参数的时间单位;
workQueue:用于在任务执行前保存任务的队列。这个队列将只保存由execute方法提交的Runnable任务;
threadFactory:执行程序创建新线程时使用的工厂;
Handler:当执行被阻塞时使用的处理程序,例如,线程边界和队列容量已经达到配置值。

通过以上初始参数,可得出ThreadPoolExecutor的任务处理规则:
优先级: corePoolSize > workQueue > maximumPoolSize > handler

3.1 当线程池中的线程数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程加入线程池,等待新任务执行。
3.2 当线程池中的线程数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么新的任务被放入缓冲队列。
3.3 当线程池中的线程数量大于corePoolSize,缓冲队列workQueue已满,线程池中的线程数量小于maximumPoolSize,建新的线程来处理被添加的新任务。
3.4 当线程池中的线程数量大于corePoolSize,缓冲队列workQueue已满,线程池中的线程数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。
3.5 当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被销毁。

4. Executors

4.1 Executors 定义了Executor、ExecutorService、ScheduledExecutorService、ThreadFactory和Callable类的工厂和实用程序方法。这个类支持以下几种方法:

  1. 创建并返回使用常用配置设置的ExecutorService。
  2. 创建并返回使用常用配置设置的ScheduledExecutorService。
  3. 创建并返回一个“包装的”ExecutorService的方法,该方法通过使特定于实现的方法不可访问来禁用重新配置。
  4. 创建并返回ThreadFactory,该ThreadFactory将新创建的线程设置为已知状态。
  5. 从其他类似闭包的表单中创建和返回Callable的方法,因此它们可以用于需要Callable的执行方法。

4.2 通过4.1 的1,2,3点可知,Executors这个工厂类可以创建并返回一些特殊的线程池。更多详细方法可阅读 Java 8 文档

几个主要的创建,返回不同类型线程池的方法:

  1. newFixedThreadPool(int nThreads,ThreadFactory threadFactory):创建一个线程池,重用固定数量的线程,在需要时使用提供的ThreadFactory创建新线程。在任何时候,大多数nThreads线程都是活动的处理任务。如果在所有线程都处于活动状态时提交了额外的任务,它们将在队列中等待,直到有线程可用。如果任何线程在关闭之前的执行过程中由于失败而终止,如果需要执行后续任务,将会有一个新的线程代替它。池中的线程将一直存在,直到它被显式关闭。
  2. newWorkStealingPool(int parallelism):创建一个线程池,该线程池维护足够的线程以支持给定的并行级别,并可以使用多个队列来减少争用。并行级别对应于活动参与或可参与任务处理的最大线程数。线程的实际数量可能会动态地增加或减少。工作窃取池不保证已提交任务的执行顺序。
  3. newSingleThreadExecutor():创建一个Executor,该Executor使用一个工作线程操作一个无界队列。(但是请注意,如果这个线程在关闭之前的执行过程中由于失败而终止,如果需要执行后续任务,将会有一个新的线程代替它。)任务保证按顺序执行,并且在任何给定的时间内都不会有超过一个任务处于活动状态。与等价的newFixedThreadPool(1)不同,返回的执行器保证不会重新配置以使用其他线程。
  4. newCachedThreadPool():创建一个线程池,该线程池根据需要创建新线程,但将在以前构造的线程可用时重用它们。这些池通常会提高执行许多短期异步任务的程序的性能。要执行的调用将重用之前构造的线程(如果可用)。如果没有可用的现有线程,则将创建一个新线程并将其添加到池中。60秒内未使用的线程将被终止并从缓存中删除。因此,空闲时间足够长的池不会消耗任何资源。注意,具有类似属性但细节不同(例如,超时参数)的池可以使用ThreadPoolExecutor构造函数创建。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值