目标

FDP已准备好了两种常用的线程池,可满足你大多时候的要求,你可直接使用。

当你需要异步发邮件、异步记录操作日志、异步发短信站信时,可使用线程池。

技术选型

解决上述问题,有两种技术方案,1是线程池,2是MQ消息队列。

FDP为你提供了线程池,已内置可直接使用,可实现异步解耦、无持久化能力、堆积能力差、延迟线程池提供了有限的失败重试能力。

若你有更高的要求,如:持久化能力、堆积能力、消息的可靠性、发布订阅模式、跨系统通知,请自行搭建MQ消息队列。

FDP的设计思路是小型单机系统使用线程池,简单快捷,满足业务要求就是最好的。当最到大型分布式系统时使用MQ消息队列。请看文档: 消息队列 MQ

线程池的配置文件

/b_shop-data/src/main/resources/spring-context-email.xml

线程池的基础知识

当向线程池添加任务时,处理过程如下:

1、如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务

2、如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列,由空闲的线程来处理任务(不会建新线程)。

3、如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务

4、如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务

5、当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数

四种拒绝策略:

1、在默认的 ThreadPoolExecutor.AbortPolicy 中,处理程序遭到拒绝将抛出运行时异常 RejectedExecutionException。

2、在 ThreadPoolExecutor.CallerRunsPolicy 中,调用者所在的线程来自行这个任务,此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。

3、在 ThreadPoolExecutor.DiscardPolicy 中,不能执行的任务将被删除。

4、在 ThreadPoolExecutor.DiscardOldestPolicy 中,如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)

两种线程池

普通线程池

这是最常用的线程池,具有普通线程池应有的特性:异步、可控制速度、有限队列

大多时候你需要使用本线程池

当业务需要线程池时,可向service层注入本线程池。如:发邮件、记录操作日志

延迟线程池

特性:异步、不可控制速度、延迟执行、无限队列

当有些任务需要失败后过n分钟再重执行时,可选用此线程池来实现。

也可立即执行,有不同的 api 提供给使用者。

应用

哪里需要就注入到哪里,按以下示例仿照使用。

普通线程池的应用
com.sicheng.common.email.EmailSenderImpl
com.sicheng.seller.site.service.SiteSendMessagsService
com.sicheng.wap.service.SiteSendMessagsService

延迟线程池的应用
com.sicheng.admin.store.service.StoreEnterAuthService
com.sicheng.admin.sys.service.SysMessageSafeService