Akka定时任务schedule()方法
Akka定时任务schedule()方法
文章目录
- Akka定时任务schedule()方法
- 什么是Akka定时任务schedule()方法?
- 如何使用Akka定时任务schedule()方法?
- 如何在actor外部获取Scheduler对象
- 为什么需要提供一个隐式的ExecutionContext对象,用于执行定时任务?
- 如何在actor内部获取Scheduler对象
- schedule()方法的格式
- Akka定时任务schedule()方法有哪些类型的延迟?
- 固定延迟
- 固定频率
- Duration类
- 总结
什么是Akka定时任务schedule()方法?
Akka定时任务schedule()方法是一种在Akka actor系统中管理周期性执行任务的方式。它可以让我们在指定的时间点或时间间隔,向actor发送消息或执行函数。它返回一个Cancellable对象,我们可以调用它的cancel()方法来取消定时任务的执行。
Akka定时任务schedule()方法是基于一个哈希轮定时器(Hashed Wheel Timer)实现的,它是一种高效的数据结构和算法,用于处理大量的定时触发事件,如actor接收超时、Future超时、断路器等。它不会精确地在指定的时间点执行任务,而是在每个滴答(tick)时,执行所有已经到期的任务。我们可以通过配置属性akka.scheduler.tick-duration
来修改Akka定时任务schedule()方法的精度。
如何使用Akka定时任务schedule()方法?
如何在actor外部获取Scheduler对象
要使用Akka定时任务schedule()方法,我们需要先获取一个Scheduler对象,它是每个ActorSystem唯一的,并且用于内部调度各种事件。我们可以通过调用ActorSystem的scheduler方法来获取它:
// 获取一个ActorSystem对象
val system = ActorSystem("akka-scheduler-system")
// 获取一个Scheduler对象
val scheduler = system.scheduler
然后,我们需要提供一个隐式的ExecutionContext对象,用于执行定时任务。我们可以使用ActorSystem自带的dispatcher作为ExecutionContext:
// 导入ActorSystem自带的dispatcher作为ExecutionContext
import system.dispatcher
为什么需要提供一个隐式的ExecutionContext对象,用于执行定时任务?
ExecutionContext
是一个表示执行上下文的特质,它可以异步地执行程序逻辑,通常但不一定是在一个线程池上
。它类似于Java的Executor接口,它有两个抽象方法:execute和reportFailure
。execute方法
用于执行一个Runnable对象,reportFailure方法
用于报告一个异步计算失败的原因。
当我们使用Akka定时任务schedule()方法创建定时任务时,我们需要提供一个ExecutionContext对象,用于执行我们传入的函数或Runnable对象。这样,我们可以控制定时任务的执行策略,例如使用哪个线程池,如何处理异常等。我们可以使用ActorSystem自带的dispatcher作为ExecutionContext,也可以自定义一个ExecutionContext。
为了方便使用,我们通常会把ExecutionContext对象作为一个隐式参数传入schedule()方法。这样,我们就不需要显式地指定ExecutionContext对象,只需要在作用域内导入或定义一个隐式的ExecutionContext对象即可。例如:
// 导入ActorSystem自带的dispatcher作为隐式的ExecutionContext
import system.dispatcher
// 创建一个定时任务,不需要显式地传入ExecutionContext
scheduler.schedule(100.millis, 1.second)(() => greeter ! greet)
或者
// 定义一个自定义的ExecutionContext作为隐式的ExecutionContext
implicit val ec: ExecutionContext = ...
// 创建一个定时任务,不需要显式地传入ExecutionContext
scheduler.schedule(100.millis, 1.second)(() => greeter ! greet)
这样,我们就可以简化代码的书写和理解,同时保留了定时任务执行策略的灵活性。
如果我们不想使用隐式参数的方式来传入ExecutionContext对象,我们可以显式地指定ExecutionContext对象,只需要在schedule()方法的最后一个参数列表中加上ExecutionContext对象即可。例如:
// 定义一个自定义的ExecutionContext对象
val ec: ExecutionContext = ...
// 创建一个定时任务,显式地传入ExecutionContext对象
scheduler.schedule(100.millis, 1.second)(() => greeter ! greet)(ec)
这样,我们就可以显式地指定ExecutionContext对象,而不依赖于作用域内的隐式参数。这种写法可能会更清晰和安全,但也会增加代码的冗余和复杂度。因此,我们应该根据具体的场景和需求来选择是否使用隐式或显式的方式来传入ExecutionContext对象。
如何在actor内部获取Scheduler对象
context
是一个ActorContext对象
,它表示一个actor的上下文信息,包括它的self
引用,它的子actor
,它的监督策略
等。context也有一个system属性
,它是一个ActorSystem对象
,表示这个actor所属的actor系统
。因此,context.system.scheduler.schedule实际上就是调用这个actor所属的actor系统的scheduler方法来创建定时任务。
这种写法通常出现在actor内部
,当我们想要在actor内部创建定时任务
时,我们可以使用context.system.scheduler.schedule
来获取Scheduler对象。例如:
// 在actor内部创建一个定时任务,向自己发送HeartBeat消息
context.system.scheduler.schedule(100.millis, 1.second)(() => self ! HeartBeat)
这样,我们就不需要显式地获取或传入ActorSystem对象,只需要使用context.system即可。
schedule()方法的格式
接下来,我们可以使用Scheduler对象的schedule()方法来创建单次执行或重复执行的定时任务。这个方法有两种重载形式:
def schedule(initialDelay: FiniteDuration, interval: FiniteDuration)(f: ⇒ Unit): Cancellable
:这个方法用于创建重复执行的定时任务,它接受三个参数:初始延迟(initialDelay),表示第一次执行任务的延迟时间;间隔时间(interval),表示每次执行任务之间的时间间隔;函数(f),表示要执行的任务。它返回一个Cancellable对象,用于取消定时任务。def schedule(initialDelay: FiniteDuration, interval: FiniteDuration, receiver: ActorRef, message: Any): Cancellable
:这个方法用于创建重复向actor发送消息的定时任务,它接受四个参数:初始延迟(initialDelay),表示第一次发送消息的延迟时间;间隔时间(interval),表示每次发送消息之间的时间间隔;接收者(receiver),表示要发送消息给哪个actor;消息(message),表示要发送什么消息。它返回一个Cancellable对象,用于取消定时任务。
如果我们只想创建单次执行或单次发送消息的定时任务,我们可以将间隔时间设置为Duration.Zero。
Akka定时任务schedule()方法有哪些类型的延迟?
Akka定时任务schedule()方法有两种类型的延迟:固定延迟(fixed-delay)和固定频率(fixed-rate)。
固定延迟
固定延迟指的是两次连续的任务执行之间的延迟时间总是至少等于给定的间隔时间。下一次任务执行的时间只有在当前任务执行完成后才会计算。如果当前任务是一个长时间运行的任务,那么下一次任务执行会延迟。因此,两次连续的任务执行之间的时间差可能不是恒定的。
例如:
// 创建一个重复向actor发送消息的定时任务,初始延迟为100毫秒,间隔时间为1秒
scheduler.schedule(100.millis, 1.second, greeter, greet)
或者
// 创建一个重复执行函数的定时任务,初始延迟为10毫秒,间隔时间为250毫秒
scheduler.schedule(10.millis, 250.millis)(() => greeter ! greet)
注意,schedule()方法只能创建固定延迟的定时任务,如果我们想创建固定频率的定时任务,我们需要使用新的scheduleAtFixedRate()方法。
从Akka 2.6版本开始,schedule()方法已经被弃用,Akka建议我们使用scheduleWithFixedDelay()方法来创建固定延迟的定时任务。所以,我们可以重写前面的例子,使用scheduleWithFixedDelay()方法:
// 创建一个重复向actor发送消息的定时任务,初始延迟为100毫秒,间隔时间为1秒
scheduler.scheduleWithFixedDelay(100.millis, 1.second, greeter, greet)
或者
// 创建一个重复执行函数的定时任务,初始延迟为10毫秒,间隔时间为250毫秒
scheduler.scheduleWithFixedDelay(10.millis, 250.millis)(() => greeter ! greet)
固定频率
固定频率指的是两次连续的任务执行之间的时间差总是等于给定的间隔时间。下一次任务执行的时间是根据上一次任务执行的时间和间隔时间来计算的。如果当前任务是一个长时间运行的任务,那么下一次任务执行可能会立即开始,或者被跳过。因此,两次连续的任务执行之间的时间差可能是恒定的,也可能是零。
从Akka 2.6版本开始,Akka建议我们使用scheduleAtFixedRate()方法来创建固定频率的定时任务。所以,我们可以重写前面的例子,使用scheduleAtFixedRate()方法:
// 创建一个重复向actor发送消息的定时任务,初始延迟为100毫秒,间隔时间为1秒
scheduler.scheduleAtFixedRate(100.millis, 1.second, greeter, greet)
或者
// 创建一个重复执行函数的定时任务,初始延迟为10毫秒,间隔时间为250毫秒
scheduler.scheduleAtFixedRate(10.millis, 250.millis)(() => greeter ! greet)
Duration类
在上一篇利用akka模拟Spark的Master与Worker通信中,为什么那篇文章里的参数里面是Duration(3,TimeUnit.SECONDS),而不是这篇提供的这种。
Duration
是一个表示时间长度的类
,它有多种构造方法,可以接受不同类型的参数。这篇提供的那种参数是使用了一个隐式转换
,把一个数字和一个时间单位组合成一个Duration对象。例如:
// 使用隐式转换,把3秒转换为一个Duration对象
3.seconds
// 等价于
Duration(3, TimeUnit.SECONDS)
这种隐式转换是由scala.concurrent.duration包提供的,它可以让我们用更简洁和直观的方式来表示时间长度。我们需要导入这个包才能使用这种隐式转换:
// 导入scala.concurrent.duration包
import scala.concurrent.duration._
所以参数里面是Duration(3,TimeUnit.SECONDS)或者3.seconds都是可以的。
参数里面是Duration(3,TimeUnit.SECONDS)可能是因为没有导入这个包,或者是为了避免歧义,或者是为了保持一致性。它们的效果是一样的,只是写法不同而已。
总结
在这篇文章中,介绍了Akka定时任务schedule()方法,它是一种在Akka actor系统中管理周期性执行任务的方式。看到了如何使用schedule()方法来创建单次执行和重复执行的定时任务,以及它们的不同类型的延迟。还了解了Akka定时任务schedule()方法的实现原理和精度问题。
相关文章:
Akka定时任务schedule()方法
Akka定时任务schedule()方法 文章目录Akka定时任务schedule()方法什么是Akka定时任务schedule()方法?如何使用Akka定时任务schedule()方法?如何在actor外部获取Scheduler对象为什么需要提供一个隐式的ExecutionContext对象,用于执行定时任务&…...
Python实现处理和分析大规模文本数据集,包括数据清洗、标注和预处理
处理和分析大规模文本数据集,包括数据清洗、标注和预处理,是自然语言处理(NLP)中非常重要的一步。Python 是一种非常流行的编程语言,拥有丰富的 NLP 库和工具,可以帮助我们完成这些任务。以下是一个简单的实现示例,包括数据清洗、标注和预处理: import re import nltk…...

灌区量测水系统
1)灌区量测水 灌区量测水是水资源管理的基础,是推进节水农业和水价改革的重要手段。常规在主要水闸处,监测闸前和闸后水位及闸门开启状态(闸位),通过实时监测数据,计算过闸流量。要实现全灌区水资源动态配置、精准灌溉࿰…...

3.3 泰勒公式
学习目标: 复习微积分基础知识。泰勒公式是微积分的一个重要应用,因此在学习泰勒公式之前,需要复习微积分的基本概念和技能,包括函数的导数和微分、极限、定积分等。可以参考MIT的微积分课程进行复习和加强。 学习泰勒级数和泰勒…...
ubuntu中通过vscode编译调试ORB-SLAM3
为了在orb-slam3的基础上进行二次开发,这几天花了不少精力,终于搞懂怎么在ubuntu系统中像windows里visual studio中一样方便的打断点调试了,在这里把整个过程再重新梳理一下。 1 首先从安装ubuntu 22.04开始 因为是从实验室毕业先辈那里继承…...

阿里版 ChatGPT 突然上线!
转自:纯洁的微笑 其实早本月初,就传出过不少阿里要推出类ChatGPT的消息。 前几天率先流出的天猫精灵“鸟鸟分鸟”脱口秀版GPT,就是基于大模型的“压缩版”,已经以其惊艳表现吸引了众目光。 如今“原版大菜”上桌,自然一点即着&a…...

《Kubernetes部署篇:Ubuntu20.04基于containerd部署kubernetes1.24.12单master集群》
一、架构图 如下图所示: 二、环境信息 主机名K8S版本系统版本内核版本IP地址备注k8s-master-621.24.12Ubuntu 20.04.5 LTS5.15.0-69-generic192.168.1.62master节点k8s-worker-631.24.12Ubuntu 20.04.5 LTS5.15.0-69-generic192.168.1.63worker节点k8s-worker-641…...

MAZDA CX-50没现车怎么办?赶紧去VR看车啊!
爱车一族往往都有过这样的经历:听说某家品牌出了一款心仪的新车,于是一直心心念念想要先睹为快。然而这时候问题就来了:新车从发布到量产上市往往要经历一段过程。没有现车的日子里,就算每天去4S店蹲守也看不到新车。那种心里痒痒…...

结构体全解,适合初学者的一条龙深度讲解(附手绘图详解)
我们知道,C语言是允许我们自己来创造类型的,这些类型就叫做——自定义类型。 自定义类型又包括结构体类型,联合体类型还有枚举类型。 今天的文章,我们就着重讲解这其中的结构体类型。 目录 结构体的声明 1.1结构的基础知识 …...
什么是SD-WAN技术?企业网络优化的利器!
现今,企业网络架构已成为其发展不可或缺的组成部分。针对网络性能优化方面,SD-WAN是一种值得深思熟虑的选择,在企业网络中应用SD-WAN技术能够带来多重好处。 什么是SD-WAN技术以及它是如何工作的? SD-WAN是软件定义的广域网&…...
JAVA练习106- 生命游戏
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、题目-生命游戏 1.题目描述 2.思路与代码 2.1 思路 2.2 代码 总结 前言 提示:这里可以添加本文要记录的大概内容: 4 月12日练习…...

【案例教程】基于R语言、MaxEnt模型融合技术的物种分布模拟、参数优化方法、结果分析制图与论文写作实践技术
【原文链接】: 基于R语言、MaxEnt模型融合技术的物种分布模拟、参数优化方法、结果分析制图与论文写作实践技术https://mp.weixin.qq.com/s?__bizMzU5NTkyMzcxNw&mid2247537049&idx3&sn31ef342c4808aed6fee6ac108b899a33&chksmfe6897f3c91f1ee5c4fa8e4eeea34…...

php7类型约束,严格模式
在PHP7之前,函数和类方法不需要声明变量类型 ,任何数据都可以被传递和返回,导致几乎大部分的调用操作都要判断返回的数据类型是否合格。 为了解决这个问题,PHP7引入了类型声明。 目前有两类变量可以声明类型: 形参&a…...

2023-04-11 无向图的匹配问题
无向图的匹配问题 之所以把无向图的这个匹配问题放到最后讲是因为匹配问题借鉴了有向图中一些算法的思想 1 最大匹配和完美匹配 二分图回顾 二分图:把一个图中的所有顶点分成两部分,如果每条边的两端分别属于不同部分,则这个图是二分图。更多…...

国家出手管人工智能AI了
我是卢松松,点点上面的头像,欢迎关注我哦! 全球都在封杀AI,国家也出手了,人工智能AI的强监管来了!这次反应速度算是很快了。国家出手,AI必须管。 国家网信办拟针对生成式人工智能服务出台管理办法&#…...
day24—选择题
文章目录1.将N条长度均为M的有序链表进行合并,合并以后的链表也保持有序,时间复杂度为(A)2.已知某个哈希表的n个关键字具有相同的哈希值,如果使用二次探测再散列法将这n个关键字存入哈希表,至少要进行&…...
自投递简历以来的第一次面试
投完简历之后HR小姐姐接着就安排了面试,原定时间是今天下午六点,我五点五十进的会议,结果等到六点二十(真的有点不耐烦了说实话)面试官打电话过来了说网络不是很好,所以改成电话面试了。 1、session信息保…...
【C++11】新特性 - 右值引用详解
文章目录STD容器使用右值引用场景移动语义在容器中的使用主要体现在两个方面:移动构造函数和移动赋值运算符。移动语义只对右值有效,对左值无效原因STD容器使用右值引用场景 移动语义在容器中的使用主要体现在两个方面:移动构造函数和移动赋…...
C++学习笔记
C学习笔记函数一般有返回值,构造函数有没有返回值?有返回值,返回一个对象,确定所以没写;在头文件中,防卫式声明,#ifndef…#define … #endif;pass by value或者 reference,传值是整包…...

项目1实现login登录功能方案设计第三版
需求优化点:MySQL表常用功能模块实现方案index页面home页面需求 实现一个登录功能 实现的功能 注册(邮箱注册)登录(邮箱密码)重置密码查看操作记录(登录, 注册, 重置密码, 登出. 都算操作)登出在第2版的基础上进行优化:\ 优化点: VerificationCode(验证码储存库): 增加时间字段…...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...

SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...