从递归练习到 Akka 心跳机制:几段 Scala 常见题目的实现思路
时间:2026-08-25 | 作者:电竞小硕 | 阅读:01.递归实现瓶盖,瓶子换酒瓶的算法
1.1 需求描述
每瓶啤酒2元,3个空酒瓶或者5个瓶盖可换1瓶啤酒。100元最多可喝多少瓶啤酒?(不允许借啤酒) 思路:利用递归算法,一次性买完,然后递归算出瓶盖和空瓶能换的啤酒数
1.2 代码实现
def extralPeer(bot: Int, cap: Int): Int = {
val count = bot / 3 + cap / 5
if (count <= 0)
return 0
val modBot = bot % 3
val modCap = cap % 5
count + extralPeer(count + modBot, count + modCap)
}
2.Scala实现猜拳游戏
2.1 需求如下
-
选取对战角色
-
开始对战,用户出拳,与对手进行比较,提示胜负信息
-
猜拳结束算分,平局都加一分,获胜加二分,失败不加分
-
循环对战,当输入“n”时,终止对战,并显示对战结果
-
游戏结束后显示得分
2.2 实现逻辑和主要代码
-
创建用户类User,定义类的属性(name,score)和类的方法(showFist())
-
创建计算机类Computer,定义类的属性(name,score)和类的方法(showFist())
-
实现计算机随机出拳
-
创建游戏类Game,定义类的属性(甲方玩家、乙方玩家、对战次数)
-
编写初始化方法、游戏开始方法
主要代码:
2.3 效果演示
def extralPeer(bot: Int, cap: Int): Int = {
val count = bot / 3 + cap / 5
if (count <= 0)
return 0
val modBot = bot % 3
val modCap = cap % 5
count + extralPeer(count + modBot, count + modCap)
}
3.用户位置时长统计sql
3.1 需求描述
现在有这么些数据亟待处理:字段包括用户ID、位置ID、开始时间以及停留时长(单位:分钟)。
4行样例数据如下:UserA,LocationA,8,60 UserA,LocationA,9,60 UserB,LocationB,10,60 UserB,LocationB,11,80。
样例数据中的数据含义为:用户UserA在LocationA位置,从8点开始,停留了60分钟。
处理要求如下:
1. 对于同一个用户在同一个位置的连续多条记录进行合并。
2. 合并原则为:开始时间取最早时间,停留时长进行累计求和。
3.2 Sql实现
select user_id, location_id, min(start_time) as start_time, sum(stay_time) as stay_time from t1 group by user_id, location_id
4.Actor间通讯
编写两个Actor, 分别是AActor和BActor,两个Actor之间可以互相发送消息
4.1主要实现
先用一个start命令启动AActor,然后给自己发 一个消息,启动go后面的流程,然后A,B互相循环发送消息
object Demo {
private val MyFactory = ActorSystem("myFactory")
// 通过MyFactory.actorOf方法来创建一个actor;
//只给A发消息,让他们两个Actor开始对话
private val bActorRef = MyFactory.actorOf(Props[BActor], "bAcator")
private val aActorRef = MyFactory.actorOf(Props(new AActor(bActorRef)), "aAcator")
def main(args: Array[String]): Unit = {
var flag = true
while (flag) {
val consoleLine: String = StdIn.readLine()
//通过!来发送消息
aActorRef ! consoleLine
if (consoleLine.equals("拜拜")) {
flag = false
println("程序即将结束!")
}
// 休眠100毫秒
Thread.sleep(100)
}
}
}
5.模拟Spark中Master与Worker进程通讯
为了加深对主从服务心跳检测机制(HeartBeat)的理解,模拟master与sla ve之间的通信。
-
Worker 注册到 Master,Master 完成注册,并回复 Worker 注册成功(注册功能)
-
Worker 定时发送心跳,并在 Master 接收到
-
Master 接收到 Worker 心跳后,要更新该 Worker 的最近一次发送心跳的时间
-
给 Master 启动定时任务,定时检测注册的 Worker 有哪些没有更新心跳,并将其从 hashmap 中删除
5.1 代码实现
需注意的是,Worker和Master均通过发送start来启动,协议是借助模板类实现的。因此,需新增几个case class,处理逻辑方面要留意客户端需发送哪些类型的消息,服务端又要接收哪些类型的消息,两者配合使用即可。代码地址为:github.com/hulichao/bi…park
主要实现:
//master消息处理
val workers = mutable.Map[String, WorkerInfo]()
override def receive: Receive = {
case "start" => {
println("master running....")
// 检查超时worker
self ! StartTimeOutWorker
}
case StartTimeOutWorker => {
println("start check timeout worker...")
// 定义定时器,每隔一段时间检查worker心跳是否超时
import context.dispatcher
context.system.scheduler.schedule(0 millis, 9000 millis, self, RemoveTimeOutWorker)
}
case RemoveTimeOutWorker => {
// 获取workers中所有workerInfo
val workerInfos = workers.values
// 获取当前时间
val currentTime = System.currentTimeMillis()
// 找出超时6秒的worker
workerInfos.filter(info => (currentTime - info.lastHeartBeatTime) > 6000)
.foreach(workers -= _.id)
println(s"===> workers.size = ${workers.size}")
}
case RegisterWorkerInfo(id, cpu, ram) => {
//判断是否已注册
if (!workers.contains(id)) {
val info =
// 添加数据
workers += (id -> new WorkerInfo(id, cpu, ram)) //worker列表添加
println("workers => 注册:" + workers)
//注册成功回复消息
sender() ! RegisteredWorkerInfo
}
}
case HeartBeat(id) => {
// 更新对应workinfo的心跳时间
// 从workers中取出workerinfo
val workerInfo = workers(id)
// 更新最后心跳时间
workerInfo.lastHeartBeatTime = System.currentTimeMillis()
println(s"master updated worker ${id}'s heartbeat")
}
//worker消息处理
override def receive: Receive = {
case "start" => {
println("worker running...")
// 发送注册信息
masterProxy ! RegisterWorkerInfo(id, 16, 16 * 1024)
}
case RegisteredWorkerInfo => {
println(s"worker ${id} registered!")
// 定义定时器,每隔一段时间告诉自己发送心跳
import context.dispatcher
// 0 millis:立即执行
// 3000 millis:每隔3秒执行
// self:接收对象,发给自己
// SendHeartBeat:发送内容
context.system.scheduler.schedule(0 millis, 3000 millis, self, SendHeartBeat)
}
//发送心跳
case SendHeartBeat => {
println(s"worker ${id} send heartbeat to master")
masterProxy ! HeartBeat(id)
}
5.3 演示
查看个人资料,可以关注更多。








