阿里规范——ScheduledExecutorService及线程池的手动创建(源码分析)

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顺便贴出阿里开发手册的下载链接

您的点赞,是我更新的动力!
如有错误,望指正

  • 16
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值