ScheduledThreadPool中的Leader-Follow模式你知道不?
点击上方蓝色“程序猿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模式你知道不?相关推荐
- half-sync/half-async 和 Leader/Followers 模式的主要区别
在 <POSA2> 一书中,关于这两个模式有两个很形象的比喻: 半同步/半异步(half-sync/half-async): 许多餐厅使用 半同步/半异步 模式的变体.例如,餐厅常常雇佣一 ...
- mysql leader/followers_half-sync/half-async 和 Leader/Followers 模式的主要区别
http://iunknown.javaeye.com/blog/60414 half-sync/half-async 和 Leader/Followers 模式的主要区别 关键字: half-syn ...
- 保姆级zookeeper集群搭建(leader+follower模式)
Zookeeper集群搭建指的是ZooKeeper分布式模式安装.通常由2n+1台server组成.这是因为为了保证Leader选举(基于Paxos算法的实现)能过得到多数的支持,所以ZooKeepe ...
- Java中的简单工厂模式(转)
Java中的简单工厂模式 举两个例子以快速明白Java中的简单工厂模式: 女娲抟土造人 话说:"天地开辟,未有人民,女娲抟土为人."女娲需要用土造出一个个的人,但在女娲造出人之前, ...
- R语言使用str_replace函数和str_replace_all函数替换字符串中匹配到的模式:str_replace函数替换第一个匹配到的字符串、str_replace_all函数替换所有匹配到的
R语言使用str_replace函数和str_replace_all函数替换字符串中匹配到的模式:str_replace函数替换第一个匹配到的字符串.str_replace_all函数替换所有匹配到的 ...
- [Head First设计模式]餐馆中的设计模式——命令模式
系列文章 [Head First设计模式]山西面馆中的设计模式--装饰者模式 [Head First设计模式]山西面馆中的设计模式--观察者模式 [Head First设计模式]山西面馆中的设计模式- ...
- .vimrc文件中的leader是什么?
我在很多.vimrc文件中看到<leader> ,我想知道它是什么意思? 它是干什么用的? 只是对目的和用法的一般概述将是伟大的. #1楼 "领导者密钥"是一种通过使用 ...
- 从脑电图(EEG)中提取稳定的模式进行识别
本篇文章是论文<Identify Stable Patterns over Time for Emotion Recognition from EEG>(<从脑电图(EEG)中提取稳 ...
- .Net中的设计模式——Iterator模式
在.Net中,我们很少有机会使用Iterator模式,因为.Net Framework已经运用Iterator模式为所有的集合对象实现了迭代器.我们在遍历集合对象时,喜欢使用C#提供的foreach语 ...
- kibana 更新 索引模式_elasticsearch – 如何在kibana中自动配置索引模式
是否可以在kibana中自动配置索引模式?通过一些设置文件或者休息api.安装后,可以手动完成. Kibana 5.x公开了这样一个API来管理索引模式. 要创建索引模式,可以向kibana访问URL ...
最新文章
- HG522-C 刷Openwrt记录
- 对于知识的可连接性的理解
- 【树链剖分】Milk Visits G(luogu 5838)
- LeetCode 1323. 6 和 9 组成的最大数字
- Centos8 搭建linux集群
- 使用PlantUML和VS Code轻松实现UML
- 图片不存在显示默认图片
- ​java/ mysql企业动态网站设计制作作业成品
- 如何选择Spark Streaming 的Reveiver和Direct模式
- 深入V8引擎-写在前面
- 在Windows Server2012系统中安装Oracle11g
- STSegmentedControl
- python 操作微信 群发_python实现给微信公众号发送消息的方法
- 如何将静态图片制作成闪图效果?
- dw超链接标签_使用Dreamweaver制作网页超链接的详细图文教程--系统之家
- 阿里面试:设计一个电商平台积分兑换系统!
- 选购羽毛球拍的初级知识
- python青蛙跳台阶_Python之青蛙跳台阶
- [转]如何解决Windows图片预览窗口无法显示图片缩略图
- 计算机类所有一级刊物,核心期刊介绍
热门文章
- eclipse 启动 找不到 JRE JDK的解决方法
- eclipse如何修改dynamic web module version
- python 获取公网 外网 ip 几种方式
- SSPI简介 windows专用GSSAPI
- EditPlus 中添加 Win32 ASM 语法支持
- 将 Hadoop YARN 发扬广大
- 华为鸿蒙系统多久上市,华为鸿蒙系统手机上市了吗 鸿蒙OS已达到安卓70-80%水平...
- mysql client 5.1.34_mysql最新版
- oracle更新快捷方式的错误,oracle 11g数据库启动错误总结
- android spinner 简书,【Android】Spinner:下拉列表笔记