目标
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