点击上方蓝色“程序猿DD”,选择“设为星标”

回复“资源”获取独家整理的学习资料!

来源 | http://8rr.co/AXCJ

ScheduledThreadPoolExecutor 是java中一个非常常用的定时调度的工具,其提供了两种定时调度常用模式:

1.固定调度周期的任务执行。

2.固定延迟间隔的任务执行,延迟间隔表示的是前一次执行完成到后一次执行开始的时间差。

1.scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)
2.scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit)

ScheduledThreadPoolExecutor 是基于ThreadPoolExecutor实现的,其继承了类ThreadPoolExecutor。从构造器可以看出,为满足定时调度的需求,其基于ThreadPoolExecutor定制了延迟工作队列DelayedWorkQueue。

public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE,DEFAULT_KEEPALIVE_MILLIS /*10L*/, MILLISECONDS,new DelayedWorkQueue());
}

DelayedWorkQueue是一个基于最小堆的队列,其在元素进出队列等BlockingQueue接口方法中使用可重入锁,以保证线程安全。为了在O(1)的时间取消特定任务的调度,ScheduleFutrueTask对象中还额外增加了heapIndex字段,以记录其在最小堆中的位置。

Leader-Follower模式

定时调度线程池与一般线程池的一个重要不同:提交的任务是延迟而非立即执行的,因此worker线程调用队列的take以取出执行任务必定是要阻塞的。考虑到等待延迟执行任务的线程无需都使用timed waiting等待队首任务,一个task的执行线程只有一个,全部唤醒只会造成大量无效的线程唤醒和阻塞操作。

ScheduledThreadPool采用了Leader-Follower模式,等待第一个线程的任务也称为leader,其调用available.awaitNanos待当前队列头部任务到达调度时间时唤醒。其余线程作为follower只需调用await方法无限阻塞等待,直至被leader唤醒,并重新完成抢锁->尝试执行队列首元素->抢leader->等待的循环。

public RunnableScheduledFuture<?> take() throws InterruptedException {final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {for (;;) {RunnableScheduledFuture<?> first = queue[0];if (first == null)available.await();else {long delay = first.getDelay(NANOSECONDS);if (delay <= 0L)return finishPoll(first);first = null; // don't retain ref while waitingif (leader != null)available.await();else {Thread thisThread = Thread.currentThread();leader = thisThread;try {available.awaitNanos(delay);} finally {if (leader == thisThread)leader = null;}}}}} finally {if (leader == null && queue[0] != null)available.signal();lock.unlock();}
}

若新增元素位于堆顶,此时需安排等待该元素定期调度或立即执行的leader线程。为此offer方法在新增元素应率先调度时,清空leader,并signal唤醒某个等待线程,继续take方法中的循环:抢锁->尝试执行队首元素->抢leader->等待。

public boolean offer(Runnable x) {final ReentrantLock lock = this.lock;lock.lock();try {/*insert into queue*/if (queue[0] == e) {leader = null;available.signal();}} finally {lock.unlock();}return true;
}

往期推荐

Spring Boot 中的 RestTemplate不好用?试试 Retrofit !

十年后,这款优秀的工具终于给出了不开源的原因

面试:讲一讲Spring中的循环依赖

IDEA不愧为神器,结合Groovy脚本,简直无敌!

记一次 Linux 被入侵,服务器变“矿机”全过程

离职成为自由开发者的100天

我在星球与你分享经验、交流成长

???? ???? ???? ????

星球两大分享内容

ScheduledThreadPool中的Leader-Follow模式你知道不?相关推荐

  1. half-sync/half-async 和 Leader/Followers 模式的主要区别

    在 <POSA2> 一书中,关于这两个模式有两个很形象的比喻: 半同步/半异步(half-sync/half-async): 许多餐厅使用 半同步/半异步 模式的变体.例如,餐厅常常雇佣一 ...

  2. mysql leader/followers_half-sync/half-async 和 Leader/Followers 模式的主要区别

    http://iunknown.javaeye.com/blog/60414 half-sync/half-async 和 Leader/Followers 模式的主要区别 关键字: half-syn ...

  3. 保姆级zookeeper集群搭建(leader+follower模式)

    Zookeeper集群搭建指的是ZooKeeper分布式模式安装.通常由2n+1台server组成.这是因为为了保证Leader选举(基于Paxos算法的实现)能过得到多数的支持,所以ZooKeepe ...

  4. Java中的简单工厂模式(转)

    Java中的简单工厂模式 举两个例子以快速明白Java中的简单工厂模式: 女娲抟土造人 话说:"天地开辟,未有人民,女娲抟土为人."女娲需要用土造出一个个的人,但在女娲造出人之前, ...

  5. R语言使用str_replace函数和str_replace_all函数替换字符串中匹配到的模式:str_replace函数替换第一个匹配到的字符串、str_replace_all函数替换所有匹配到的

    R语言使用str_replace函数和str_replace_all函数替换字符串中匹配到的模式:str_replace函数替换第一个匹配到的字符串.str_replace_all函数替换所有匹配到的 ...

  6. [Head First设计模式]餐馆中的设计模式——命令模式

    系列文章 [Head First设计模式]山西面馆中的设计模式--装饰者模式 [Head First设计模式]山西面馆中的设计模式--观察者模式 [Head First设计模式]山西面馆中的设计模式- ...

  7. .vimrc文件中的leader是什么?

    我在很多.vimrc文件中看到<leader> ,我想知道它是什么意思? 它是干什么用的? 只是对目的和用法的一般概述将是伟大的. #1楼 "领导者密钥"是一种通过使用 ...

  8. 从脑电图(EEG)中提取稳定的模式进行识别

    本篇文章是论文<Identify Stable Patterns over Time for Emotion Recognition from EEG>(<从脑电图(EEG)中提取稳 ...

  9. .Net中的设计模式——Iterator模式

    在.Net中,我们很少有机会使用Iterator模式,因为.Net Framework已经运用Iterator模式为所有的集合对象实现了迭代器.我们在遍历集合对象时,喜欢使用C#提供的foreach语 ...

  10. kibana 更新 索引模式_elasticsearch – 如何在kibana中自动配置索引模式

    是否可以在kibana中自动配置索引模式?通过一些设置文件或者休息api.安装后,可以手动完成. Kibana 5.x公开了这样一个API来管理索引模式. 要创建索引模式,可以向kibana访问URL ...

最新文章

  1. HG522-C 刷Openwrt记录
  2. 对于知识的可连接性的理解
  3. 【树链剖分】Milk Visits G(luogu 5838)
  4. LeetCode 1323. 6 和 9 组成的最大数字
  5. Centos8 搭建linux集群
  6. 使用PlantUML和VS Code轻松实现UML
  7. 图片不存在显示默认图片
  8. ​java/ mysql企业动态网站设计制作作业成品
  9. 如何选择Spark Streaming 的Reveiver和Direct模式
  10. 深入V8引擎-写在前面
  11. 在Windows Server2012系统中安装Oracle11g
  12. STSegmentedControl
  13. python 操作微信 群发_python实现给微信公众号发送消息的方法
  14. 如何将静态图片制作成闪图效果?
  15. dw超链接标签_使用Dreamweaver制作网页超链接的详细图文教程--系统之家
  16. 阿里面试:设计一个电商平台积分兑换系统!
  17. 选购羽毛球拍的初级知识
  18. python青蛙跳台阶_Python之青蛙跳台阶
  19. [转]如何解决Windows图片预览窗口无法显示图片缩略图
  20. 计算机类所有一级刊物,核心期刊介绍

热门文章

  1. eclipse 启动 找不到 JRE JDK的解决方法
  2. eclipse如何修改dynamic web module version
  3. python 获取公网 外网 ip 几种方式
  4. SSPI简介 windows专用GSSAPI
  5. EditPlus 中添加 Win32 ASM 语法支持
  6. 将 Hadoop YARN 发扬广大
  7. 华为鸿蒙系统多久上市,华为鸿蒙系统手机上市了吗 鸿蒙OS已达到安卓70-80%水平...
  8. mysql client 5.1.34_mysql最新版
  9. oracle更新快捷方式的错误,oracle 11g数据库启动错误总结
  10. android spinner 简书,【Android】Spinner:下拉列表笔记