阿里规范——ScheduledExecutorService及线程池的手动创建(源码分析)
4月22日阿里官方又推出了最新的JAVA开发手册1.6(泰山版)。仁者见仁,对于我而言,开发手册不断在帮我改善着代码中根深蒂固的小陋习,个人觉得还是有很大帮助。(ps:文章下载链接)言归正传,当你在代码中使用到Timer这个定时器时,阿里的开发插件会有如下提示多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用Sche...
4月22日阿里官方又推出了最新的JAVA开发手册1.6(泰山版)。仁者见仁,对于我而言,开发手册不断在帮我改善着代码中根深蒂固的小陋习,个人觉得还是有很大帮助。(ps:文章最后附下载链接)
言归正传,当你在代码中使用到Timer这个定时器时,阿里的开发插件会有如下提示
多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,
其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题。
//org.apache.commons.lang3.concurrent.BasicThreadFactory
ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
new BasicThreadFactory.
Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
executorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
//do something
}
},initialDelay,period, TimeUnit.HOURS);
ScheduledExecutorService
这是一种线程池的方式执行定时任务,说到ScheduledExecutorService,网上很多都是使用
Executors.newSingleThreadScheduledExecutor();方式创建。阿里规范在对线程池的创建也有强制的约定。
下面就是 ScheduledExecutorService的 scheduleAtFixedRate方法使用
executorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
//do something
}
},initialDelay,period, TimeUnit.HOURS);
//do something: 就是你自己的需要做的业务逻辑
initialDelay: 延迟时间,一般设为0 立即执行
period:周期 每 周期执行一次
TimeUnit.HOURS(小时):时间单位, TimeUnit.SECONDS(秒),TimeUnit.MILLISECONDS(毫秒)
自己配置以上参数
只想满足基本需求就可以不用往下继续阅读了。
ScheduledExecutorService的手动创建
ScheduledExecutorService的手动创建方式
ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
new BasicThreadFactory.
Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
这里我们肯定主要关心的是 ScheduledExecutorService 是怎样创建的,点进ScheduledThreadPoolExecutor的源码,我们可以看到
我们可以看到有两个参数:corePoolSize ThreadFactory
corePoolSize :核心线程数
ThreadFactory:线程工厂
继承自ThreadPoolExecutor类
int corePoolSize:核心线程数
int maximumPoolSize:最大线程数量
long keepAliveTime:当线程池中的线程数大于 corePoolSize 时,keepAliveTime 为多余的空闲线程等待新任务的最长时间,超过这个时间后多余的线程将被终止。所以,如果任务很多,并且每个任务执行的时间比较短,可以调大时间,提高线程的利用率
TimeUnit unit:keepAliveTime的时间单位
BlockingQueue workQueue 任务队列
RejectedExecutionHandler handler: 达到了线程界限和队列容量时的处理方案(拒绝策略)
构造的时候corePoolSize的数量是自己定义的, ThreadFactory也是自己构造的
我们在这里设置corePoolSize的数量为 1,最大线程数为最大的整数类型,但是keepAliveTime的时间却设置为0,意思就是不让(除核心线程外的)其他线程等待,只留核心线程。NANOSECONDS纳秒,DelayedWorkQueue()优先级队列,threadFactory自己构造的线程工厂。
ThreadPoolExecutor 的源码分析就到这,下面看下阿里构造的这个ThreadFactory
new BasicThreadFactory.Builder().
namingPattern(“example-schedule-pool-%d”).daemon(true).build()
我们就分析上面的这个构造函数,就不做其他延伸了。
.Builder() 是一个无参构造
.namingPattern(“example-schedule-pool-%d”)
这里只做了非空判断
**.daemon(true)**是否守护线程
**.build()**讲上面两个参数传入到构造返回 BasicThreadFactory
其中这个namingPattern(“example-schedule-pool-%d”),我很少看到有人对这属性进行分析
我找到官网对于这个属性的描述 下面是谷歌翻译
可以为此工厂创建的线程指定名称模式。如果应用程序出于不同目的使用多个执行程序服务,这通常很有用。如果这些服务使用的线程名称具有有意义的名称,则日志输出或异常跟踪可能更易于阅读。命名模式是该方法使用的格式字符串String.format()。该字符串可以包含占位符%d ,该占位符将被当前线程的编号替换(ThreadFactoryImpl保留其已经创建的线程的计数器)。例如,命名模式"My %d. worker thread"将导致诸如的线程名称"My 1. worker thread","My 2. worker thread"依此类推
ps感兴趣的可以看看 BasicThreadFactory的官方说明
ps顺便贴出阿里开发手册的下载链接
您的点赞,是我更新的动力!
如有错误,望指正
更多推荐
所有评论(0)