While模式严格来说是while循环在Akka中的合理实现。while是开发过程中经常用到的语句之一,也是绝大部分编程语言都支持的语法。但while语句是一个循环,如果循环条件没有达到会一直执行while语句体的代码,且会阻塞while语句外的代码。如果在Akka中简单的使用while语句会极大的限制当前actor的功能。

object GeneralWhile {
def main(args: Array[String]): Unit = {
var i=0
val maxLine = 10
while(i<maxLine){
println(i)
i += 1
}
}
}

输出:

0
1
2
3
4
5
6
7
8
9

  上图是while语句的常规用法,打印了从0-9的数字。如果这段代码出现在了actor对某个消息的处理过程中,就会带来其他的问题和不便。

class WhileActor extends Actor{
override def receive: Receive = {
case "start" =>
println("do start work")
var i=0
val maxLine = 10
while(i<maxLine){
println(i)
i += 1
}
println("start work done")
case "others" =>
println("do other work")
}
}
object WhilePattern1 {
def main(args: Array[String]): Unit = {
val system = ActorSystem("WhilePattern1",ConfigFactory.load())
val whileActor = system.actorOf(Props(new WhileActor),"WhilePattern1")
whileActor ! "start"
whileActor ! "others"
}
}

输出:

do start work
0
1
2
3
4
5
6
7
8
9
start work done
do other work

  上面代码是actor中简单使用while的例子。其实在简单的业务场景下,这种实现并没有太大问题,只不过while可能会阻塞当前actor而已。不过while有一个极端的情况,那就是while死循环。虽然死循环不能轻易出现,不过也非常有用。比如有以下场景:循环读取数据库做某种操作。在Akka的消息处理过程中是绝对不能出现死循环的,一旦出现死循环这个actor基本就废了(因为阻塞到了这个方法处理)!

  其实如果你的业务需求需要在Akka中使用死循环,而且你也的确这么用了,那只能说明对Actor模型不熟悉,因为Actor模型本身对消息的处理就是“死循环”。为什么说actor本身就是一个“死循环"呢?actor在收到消息会进行对应的处理,死循环也就意味着一直收到消息,那么如何一直收到消息呢?其他actor给它发消息或者自己给自己发消息,很显然,actor内部的循环逻辑跟其他actor关系不大,发消息给自己是比较合理的。

  

class WhileForeverActor extends Actor{
var condition = true
override def preStart(): Unit = {
super.preStart()
self ! "doWork"
}
override def receive: Receive = {
case "doWork" =>
println("从数据库获取n条数据循环处理")
Thread.sleep(1000)
println("处理完毕")
if(condition){
self ! "doWork"
}
case "otherWork" =>
println("处理其他消息")
}
}
object WhilePattern2 {
def main(args: Array[String]): Unit = {
val system = ActorSystem("WhilePattern2",ConfigFactory.load())
val whileActor: ActorRef = system.actorOf(Props(new WhileForeverActor),"WhilePattern2")
Thread.sleep(3*1000)
whileActor ! "otherWork"
whileActor ! "otherWork"
}
}

输出:

从数据库获取n条数据循环处理
处理完毕
从数据库获取n条数据循环处理
处理完毕
从数据库获取n条数据循环处理
处理完毕
处理其他消息
处理其他消息
从数据库获取n条数据循环处理
处理完毕
从数据库获取n条数据循环处理
处理完毕
从数据库获取n条数据循环处理
处理完毕
从数据库获取n条数据循环处理

  上面是Akka中的while模式。简单点说,就是用自身消息驱动acotor的循环处理。这样做的好处就是可以在某次循环结束后及时的处理其他类型的消息,而不至于阻塞当前的actor,而且可以随时通过发消息的形式中断循环或修改循环条件。

   本文介绍了Akka中的while设计模式,该模式虽然简单,但也都是Akka初学者经常会遇到也最容易设计不当的情形。希望大家好好掌握该设计模式,设计出更优秀的代码。

akka设计模式系列-While模式的更多相关文章

  1. akka设计模式系列-Chain模式

    链式调用在很多框架和系统中经常存在,算不得上是我自己总结的设计模式,此处只是简单介绍在Akka中的两种实现方式.我在这边博客中简化了链式调用的场景,简化后也更符合Akka的设计哲学. trait Ch ...

  2. akka设计模式系列-Backend模式

    上一节我们介绍了Akka使用的基本模式,简单点来说就是,发消息给actor,处理结束后返回消息.但这种模式有个缺陷,就是一旦某个消息处理的比较慢,就会阻塞后面所有消息的处理.那么有没有方法规避这种阻塞 ...

  3. akka设计模式系列-Aggregate模式

    所谓的Aggregate模式,其实就是聚合模式,跟masterWorker模式有点类似,但其出发点不同.masterWorker模式是指master向worker发送命令,worker完成某种业务逻辑 ...

  4. akka设计模式系列-基础模式

    本文介绍akka的基本使用方法,由于属于基础功能,想不出一个很高大上的名称,此处就以基础模式命名.下文会介绍actor的使用方法,及其优劣点. class SimpleActor(name:Strin ...

  5. akka设计模式系列-慎用ask

    慎用ask应该是Akka设计的一个准则,很多时候我们应该禁用ask.之所以单独把ask拎出来作为一篇博文,主要是akka的初学者往往对ask的使用比较疑惑. "Using ask will ...

  6. akka设计模式系列-消息模型(续)

    在之前的akka设计模式系列-消息模型中,我们介绍了akka的消息设计方案,但随着实践的深入,发现了一些问题,这里重新梳理一下设计方法,避免之前的错误.不当的观点给大家带来误解. 命令和事件 我们仍然 ...

  7. akka设计模式系列

    由于本人爱好Scala,顺便也就爱好Akka,但目前网上对Akka的介绍大多都是概念上或技术方向上的介绍,基本没有Akka设计模式或者Actor模型设计模式的资料.这对于Akka的普及非常不利,因为即 ...

  8. PHP设计模式系列 - 外观模式

    外观模式 通过在必需的逻辑和方法的集合前创建简单的外观接口,外观设计模式隐藏了调用对象的复杂性. 外观设计模式和建造者模式非常相似,建造者模式一般是简化对象的调用的复杂性,外观模式一般是简化含有很多逻 ...

  9. akka设计模式系列-actor锚定

    actor锚定模式是指使用actorSelection对acor进行锚定的设计模式,也可以说是一个对actor的引用技巧.在某些情况下,我们可能需要能够根据Actor的path锚定对应的实例.简单来说 ...

随机推荐

  1. [Python数据结构] 使用 Circular List实现Queue

    [Python数据结构] 使用 Circular List实现Queue 1. Queue队列,又称为伫列(queue),是先进先出(FIFO, First-In-First-Out)的线性表.在具体 ...

  2. 2.5.5 基本的 I/0 重定向

        标准输入/输出(standard I/O)可能是软件设计原则里最重要的概念了.这个概念就是:程序应该有数据的来源端.数据的目的端以及报告问题的地方,它们分别被称为标准输入(standard i ...

  3. linux下使用tomcat下载中文文件报404not find

    首先,大神指路:http://bbs.csdn.net/topics/391065011?page=1 相关的一些命令: 查看当前系统字符编码:env locale 查看系统支持的字符编码:local ...

  4. Leetcode 99.恢复二叉搜索树

    恢复二叉搜索树 二叉搜索树中的两个节点被错误地交换. 请在不改变其结构的情况下,恢复这棵树. 示例 1: 输入: [1,3,null,null,2] 输出: [3,1,null,null,2] 示例  ...

  5. 解决win10磁盘占用过大的问题(亲测有效)

    问题:打开任务管理器,经常会发现磁盘占用95%以上,电脑很卡,下面是解决方案 方法: 1.关闭家庭组. (1)搜索服务,找到“HomeGroupListener”服务,右键单击“属性”.在弹出属性界面 ...

  6. go语言slice的理解

    Golang slice yongsean  作者 2017.02.17 00:07  打开App 创建切片,len.cap.append b := make([]int, 5) println(le ...

  7. Android Studio怎样改动快捷键

    在Android Studio中.如果你认为某个快捷键太复杂,要想改动.怎么改动呢,首先要找到这个快捷键,可是Android Studio搜索快捷键有一个bug,就是你不能依据快捷键来搜索相应的功能点 ...

  8. scikit-learn: isotonic regression(保序回归,非常有意思,仅做知识点了解,但差点儿没用到过)

    http://scikit-learn.org/stable/auto_examples/plot_isotonic_regression.html#example-plot-isotonic-reg ...

  9. Swift 中枚举

    Swift 中枚举高级用法及实践 字数11017 阅读479 评论0 喜欢20 title: "Swift 中枚举高级用法及实践"date: 2015-11-20tags: [AP ...

  10. Unity学习笔记(4) --- Unity的界面排版:初识GUI

    GUI和GUILayout是Unity提供的UIKit.在使用GUI的Controls时都要求设置Rect參数.没办法做到自己主动排版,给适配带来难度.而GUILayout的设计就是为了弥补这个缺陷, ...