Actors in Scala(Scala中的Actor)(预打印版) 第六章 Exception Handling, Actor Termination and Shutdown(A)

为什么 scala无法导入 scala.actors.Actor 如下图: maven官网可以看到 scala2.12和该版本后不支持actors.Actor了 所以要想用 请切换到低版本 或者使用akka的actor: import akka.actor.Actor 阅读详情
Actors in Scala(Scala中的Actor)(预打印版) 第六章 Exception Handling, Actor Termination and Shutdown(A)

张贵宾

guibin.beijing@gmail.com

2011.10.31

在这一章中我们看看如何在并行的基于actor的程序中处理错误。Actors与顺序的Scala代码相比,提供了几种处理异常的额外方法。特别的,我们将展示actor如何处理他们抛出的但不能被其他actor处理的异常。更普遍的,我们将寻找一种actor能够监控其他actor的方式,通过这种方式能够检测到其他的actor是正常的终止了,还是抛出异常后非正常退出了。最后,我们介绍了一些概念和技术,这些概念和技术能够简单的终止基于actor程序的管理。


6.1 Simple exception handling(简单异常处理)

当一个actor在其执行体内抛出了未被处理的异常后,此actor便会终止。出现这种情况的一种可能征兆就是有其他的actor在无限制的等待这个来自已经死去的actor的消息。因为在默认情况下,终止actor不会产生任何死锁,所以找到发生错误的actor和定位错误的actor就非常耗时。


最简单看护那些由于异常抛出而默默终止的actor的方法就是提供一个全局的异常处理器,任何一个actor执行体内有异常抛出时都会调用这个异常处理器。我们可以继承Actor(或者Reactor)并重写它的exceptionHandler成员函数即可。(exceptionHandler成员函数定义在Reactor中,而Actor中的继承关系是:ReplyActor继承自Reactor,Actor继承自Reactor)在Reactor中,exceptionHandler成员函数的签名是:def exceptionHandler: PartialFunction[Exception, Unit]

object A extends Actor {
  def act() {
    react {
      case 'hello =>
        throw new Exception("Error!")
    }
  }

  override def exceptionHandler = {
    case e: Exception =>
      println(e.getMessage)
  }
}

正如你所看到的,exceptionHandler是一个没有参数的,且返回值是偏函数的方法,在这里它能够处理java.lang.Exception类型的异常。任何时候从actor的函数体中抛出一个异常通常都会导致actor终止运行,当抛出异常时,运行时系统会检测actor的exceptionHandler方法能否匹配到抛出的异常类型,如果能匹配到,exceptionHandler偏函数就被应用到这个异常上,调用完exceptionHandler之后,actor会正常的终止运行。


上面的代码展示了如何复写exceptionHandler方法之后让它返回一个客户化的偏函数。下面让我们使用Scala的解释shell与actor A交互看看效果:

scala> import scala.actors._
import scala.actors._

scala> object A extends Actor {
     |   def act() {
     |     react {
     |       case 'hello =>
     |         throw new Exception("Error!")
     |     }
     |   }
     | 
     |   override def exceptionHandler = {
     |     case e: Exception =>
     |       println(e.getMessage)
     |   }
     | }
defined module A

scala> A.start
res0: scala.actors.Actor = A$@65dfb0b5

scala> A ! 'hello

scala> Error!

正像我们所期望的,exceptionHandler方法运行了,因此打印出了抛出异常上附带的消息字符串:"Error!"


使用exceptionHandler这种形式的异常处理与诸如loop这样的控制流组合器一同工作的非常好,组合器能被用于在处理了异常之后,恢复正常执行的actor。比如我们把actor A中act方法修改成如下形式:

object A extends Actor {
  def act() {
    var lastMsg: Option[Symbol] = None
    loopWhile(lastMsg.isEmpty || lastMsg.get != 'stop) {
      react {
        case 'hello =>
          throw new Exception("Error!")
        case any: Symbol =>
          println("your message: " + any)
          lastMsg = Some(any)
      }
    }
  }

  override def exceptionHandler = {
    case e: Exception =>
      println(e.getMessage)
  }
}

react方法的调用现在被包裹在了loopWhile中,loopWhile会测试最后收到的消息是否等于 'stop ,如果等于则终止actor。现在,如果actor收到一条 'hello 消息,它将抛出异常,这个异常将会被exceptionHandler处理,处理完毕异常之后actor不会终止运行,而是通过继续执行下一个loop迭代而恢复运行。这就意味着在处理完毕了异常之后,actor能够继续工作,继续准备接收更多的消息。


下面我们在Scala的命令行中测试一下:

scala> import scala.actors._
import scala.actors._

scala> object A extends Actor {
     |   def act() {
     |     var lastMsg: Option[Symbol] = None
     |     loopWhile(lastMsg.isEmpty || lastMsg.get != 'stop) {
     |       react {
     |         case 'hello =>
     |           throw new Exception("Error!")
     |         case any: Symbol =>
     |           println("your message: " + any)
     |           lastMsg = Some(any)
     |       }
     |     }
     |   }
     | 
     |   override def exceptionHandler = {
     |     case e: Exception =>
     |       println(e.getMessage)
     |   }
     | }
defined module A

scala> A.start
res0: scala.actors.Actor = A$@52620402

scala> A ! 'hello

scala> Error!


scala> A.getState
res2: scala.actors.Actor.State.Value = Suspended

scala> A ! 'hi
your message: 'hi

scala> A ! 'stop
your message: 'stop

scala> A.getState
res5: scala.actors.Actor.State.Value = Terminated


注意在发送了 'hello 之后,actor A最终暂停,等待下一条消息的到来。getState方法能够用来查询actor的执行状态,它会返回Actor.State类型的枚举类型,这些类型都定义在scala.actors.Actor对象中。Suspended状态表示actor已经调用了react方法,目前正在等待合适的(能匹配得上的)消息。因此,我们能够继续发送 'hi 消息和actor交互。在actor收到了 'stop 消息之后,它的loopWhile循环终止,actor也正常的终止了,因此最终actor的状态是Terminated。


基于SHIS凝视型短波红外高光谱相机(900-1700nm)区分不同宝石的差异性和可分性(宝石分选) SHIS系列凝视型高光谱相机基于液晶可调谐滤波器(LCTF),通过电控LCTF进行连续细分窄波段分光,对每个波段进行高分辨率的二维面阵成像,进行图像处理后,获得完整的高光谱高清图像序列。具有低功耗、小型化、使用方便和易于扩展的优势。其工作波段覆盖400nm至1000nm,能够捕捉宝石在不同波长下的光谱特征,为宝石鉴定提供了新的工具。 阅读详情

相关推荐

银河麒麟V10 SP1忘记密码?3分钟搞定单用户模式密码重置(附详细截图)

本文详细介绍了银河麒麟V10 SP1操作系统忘记登录密码后的应急恢复方法。核心是通过GRUB引导菜单进入单用户模式,无需密码即可获得root权限,从而快速重置用户密码。文章提供了从捕捉GRUB界面、编辑启动参数到执行密码修改命令的完整步骤图解与常见问题解决方案,帮助用户在几分钟内恢复系统访问。

w3x4y的博客 913

解决scala 2.10.X 无法导入 actors的问题

import scala.actors.Actor 在pom.xml中添加scala.actors依赖,然后更新 <dependency> <groupId>org.scala-lang</groupId> <artifactId>scala-actors</artifactId> <version>2.10.7</version> </dependency> 资料: https://s

枪枪枪的博客 1116

C/C++ 计算程序运行的时间

C/C++计算程序执行时间的方法,精度依次增加,推荐度也依次增加 1.#include <time.h> clock_t start, finish; double process_interval ; start=clock(); process(); //要计时的程序 finish=clock(); process_interval =(double)(finish-star...

stu_shanghui的博客 1020

Actor系统的错误处理

Actor的层次结构 Guardian Actor Actor路径 一个Actor层次机构的示例 崩溃了怎办 监管策略 指令 默认策略 Actor的生命周期 Actor的消亡 自愈系统 错误的核心 超时 Death Watch 总结 本文原文标题:《The Neophyte’s Guide to Scala Part 15: Dealing With Failure in Actor Systems

Laurence的技术博客 7462

欧姆龙NX控制器与Sysmac studio的电机配置方法

使用歐姆龍NX控制器與Sysmac studio控制電機簡單運動 <上> — 環境配置0. 前言1. 實際硬件連接2. Sysmac studio 配置2.1 新建工程2.2 通信設置2.2.1 軟件內通信設置2.2.2 上位機本地通信設置 0. 前言 筆者最近需要使用到歐姆龍的多軸運動控制器來控制電機運動,但網路上關於Sysmac studio的教程或文章較為零散,作為初學者的筆者難以消化,故在稍微會用軟件後撰寫本文,為自己留個筆記,同時希望能夠幫助到需要的人。 1.本文面向買了歐姆龍控制器

weixin_46005653的博客 1万+

# ubuntu 系统使用 yum命令报错 There are no enabled repos.Run “yum repolist all“ to see the repos you have...

# ubuntu 系统使用 yum命令报错 There are no enabled repos.Run "yum repolist all" to see the repos you have.You can enable repos with yum-config-manager --enable

段子手168的博客 6681

Scala AKKa actor 方案解决

问题:应用程序actor创建并发解决方法:继承akka.actor.Actor类来创建一个actor,在类里实现receive方法,用case语句实现问题:新建Akka actor 其构造函数有多个参数解决方法:使用Props类创建一个或包含多个参数的actor问题:构建一个基于actor应用并且在actor之间传递消息解决方法:Actor应该用!方法发送不可变消息问题:创建复杂的actor解决方...

Andwerwu的博客 854

Geant4 学习笔记(一):实现multi-thread多线程

简单修改实现Geant4多线程

weixin_52417815的博客 6084

Scala并发编程

1. 使用Actor的并发 Scala的actor提供了一种基于事件的轻量级线程。只要使用scala.actors.Actor伴生对象的actor方法,就可以创建一个actor。它接受一个函数值/闭包做参数,一创建好就开始运行。用!()方法给actor发消息,用receive()方法从actor接收消息。receive()也可以闭包为参数,通常用模式匹配处理接收到的消息。 我们看个例子,假定我...

weixin_34332905的博客 229

基于STM32F407的摄像头(不带FIFO的OV7670)图像采集及LCD显示实验-笔记整理

硬件说明 STM32F4开发板 stm32f4系列的芯片处理的能力可以说非常强大了的,而且内部还自带有数字摄像头接口(DCMI),可以说stm32f407的核心板和不带FIFO的摄像头模块OV7670简直就是绝配! 我手上的这块张这个样子 (图片来源:某宝): F4系列的DCMI接口内部结构框图如下图3所示,具体的配置使用方式可以参考以下这篇博文:《stm32f4的数字摄像头接口(DCMI)使用》 这位博主大大已经很详细地介绍了DCMI接口的具体使用方法和原理,更重要的是里面还有接口的配置函数,虽然不完

LiangWF22的博客 2万+

GAMES101学习-第8课进行shader的初步了解

详细理解课上展示的像素着色器GLSL,以及了解了API、OpenGL、DirectX到底是什么,还有shadertoy这个网站的初步探索。

qq_41835314的博客 1917

Actors in Scala(Scala中的Actor)(预打印版) 第六章 Exception Handling, Actor Termination and Shutdown(A)...

Actors in Scala(Scala中的Actor)(预打印版) 第六章Exception Handling, Actor Termination and Shutdown(A) 张贵宾 guibin.beijing@gmail.com 2011.10.31 在这一章中我们看看如何在并行的基于actor的程序中处理错误。Actors与顺序的Scala代码相比,提供了几种处...

蓝色妖姬 165

告别过热焦虑:用Ansys Icepak给你的电子设备做个“水冷体检”(附冷板案例全流程)

本文详细介绍了如何利用Ansys Icepak进行电子设备水冷系统的热仿真分析,帮助工程师解决设备过热问题。通过冷板案例全流程演示,展示了从几何处理、材料设定到求解器设置和后处理的关键步骤,提升散热设计效率与准确性。

weixin_29299807的博客 440

Scala Actor并发编程

Scala 并发编程介绍,Scala Actor实例及匿名Actor创建方法。最后介绍Scala Actor和case class 以及接收回传消息的方法。

残缺的孤独 4876

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Scala Actor(一):简单入门

(ps:虽然scala.actors最近被抛弃,但可作为新手入门理解scala的并发编程原理) 原博文地址为:http://blog.youkuaiyun.com/yyywyr/article/details/50465411 原文如下: Java中的并发编程主要通过线程实现的,通过共享资源的机制实现并发,但会面临着死锁的问题。在Scala中,是通过消息传递来实现并发的,而Actor正是实现消息

残缺的歌的专栏 1208

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

深入理解Scala默认参数函数:从方法重载到优雅API设计

我写这篇文章的时候,特意没罗列默认参数有多少种用法——因为用法很简单,谁都能写。默认参数为什么重要?可选参数。Java里你想要可选参数?写重载方法。想要几个?写一堆。代码臃肿,维护痛苦。Scala的默认参数把这件事简化了——一行函数签名,编译器帮你生成所有的重载方法。调用方想用默认值就用默认值,想改哪个就改哪个,不用管顺序。把重复的事情交给编译器,让程序员专注在业务逻辑上。你不用手写重载方法——编译器帮你写。你不用记参数顺序——命名参数帮你记。你不用写Builder类——默认参数就是Builder。

https://starzy1990.github.io/ 749

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

深入理解Scala嵌套函数:作用域封装之道

我写这篇文章的时候,特意没罗列嵌套函数有多少种写法——因为写法很简单,谁都能写。嵌套函数为什么重要?辅助逻辑的作用域应该是多大?Java里你写辅助逻辑,只能写到类级别——因为Java的方法必须定义在类级别。但很多辅助逻辑其实只属于某一个函数,不属于整个类。你把它们写到类级别,就造成了作用域放大——本来应该是函数内部的东西,变成了类级别的东西。Scala的嵌套函数把这个问题解决了——辅助逻辑可以精确地封装在主函数内部。它直接访问外层函数的变量,不用把上下文传来传去。它不暴露到类级别,不造成API膨胀。

https://starzy1990.github.io/ 738

深入理解Scala可变参数函数:从Java数组语法到优雅集合传递

我写这篇文章的时候,特意没罗列可变参数有多少种用法——因为用法很简单,谁都能写。Scala的可变参数为什么比Java好用?不是因为它有:_*这个语法——而是因为它的底层是Seq,不是数组。Java的可变参数是数组的语法糖——你传List进去,它不认,因为List不是数组。你想传?自己转。Scala的可变参数是Seq的语法糖——你传任何序列进去,只要用:_*展开就行。不用转,不用强转,一行代码搞定。**这就是函数式语言的设计哲学:可变参数不是"数组的便捷写法",它是"序列的便捷写法"。

https://starzy1990.github.io/ 440

深入理解Scala Map:从实现原理到工程实践

我写这篇文章的时候,特意没罗列Map有多少个方法——因为那些东西官方文档都有,查一下就行。Map到底解决了什么问题?它不是"带key的列表",它是一个"从key到value的映射函数"。它用哈希表的O(1)查找,换来了通过key快速找到value的能力。在大数据开发里,Map无处不在——维度关联、配置映射、计数统计、分组聚合、缓存索引。理解了Map,你就理解了大数据处理里最核心的几个操作:查找、映射、聚合。很多人用了几年Map,还停留在"new一个HashMap,然后put put put"的阶段。

https://starzy1990.github.io/ 390

深入理解Scala匿名函数:函数式编程基石

我写这篇文章的时候,特意没罗列匿名函数有多少种写法——因为写法很简单,谁都能写。匿名函数为什么是函数式编程的基石?把函数当参数传。你不能把函数当参数传,就没有map、filter、reduce这些集合操作。没有这些集合操作,就没有声明式编程。没有声明式编程,就没有函数式编程。Java花了很长时间才意识到这一点——Java 8才加了Lambda。但Java的Lambda是不完整的——它只能捕获final变量,不能修改变量。它是一个"阉割版"的闭包。Scala呢?

https://starzy1990.github.io/ 518

Scala List操作:不可变链表的函数式美学

Scala的List,表面上是Java List的"Scala版",本质上是函数式编程的核心数据结构——不可变的链表,配合模式匹配和递归,构成了声明式数据处理的基础。天然线程安全:不可变对象不需要锁,在多线程环境下可以安全共享结构共享:操作List时可以复用大部分结构,性能更好函数式友好:map/filter/reduce不修改原List,可以组合、可以嵌套这些特性不是孤立的,它们共同支撑了Scala的函数式编程范式。

https://starzy1990.github.io/ 1338

【Spark】 04键值对 RDD:创建、常用操作与数据分区

介绍 Spark 键值对 RDD 的创建方式、聚合、分组、连接、排序与行动操作,并结合 PageRank 示例讲解数据分区、分区器复用与自定义分区方式。

qq_46126258的博客 370

大数据Spark(八十二):Spark 算子综合案例

本文通过四个典型Spark算子应用案例,系统讲解了单词频次过滤、PV/UV统计、二次排序及分组取TopN的实现方法。涵盖flatMap、mapToPair、reduceByKey、distinct、sortByKey、groupByKey等核心算子的组合使用,提供Java与Scala双语言实现,兼顾可读性与实用性。强调根据数据规模选择合适方案,避免内存溢出,适用于大数据处理场景的实战参考。

Lansonli(蓝深李)的博客 613

深入理解Scala递归函数:从栈溢出到尾调用优化

我写这篇文章的时候,特意没罗列递归有多少种写法——因为递归的语法很简单,谁都能写。为什么Java的递归会栈溢出,而Scala的不会?不是因为Scala更厉害——而是因为Scala是函数式语言,递归是它的核心特性之一。它从设计之初就考虑了尾调用优化的问题。Java是命令式语言,它的核心是对象和方法,递归只是一个"能用但不推荐"的特性。Java程序员写递归:栈溢出,不敢用Scala程序员写递归:尾递归,随便写递归不是洪水猛兽,栈溢出是因为你没写对。你可以用递归的优雅写法,获得循环的性能。

https://starzy1990.github.io/ 614

深入理解Scala可变Map:动态构建场景下的性能与设计权衡

我写这篇文章的时候,特意没罗列可变Map有多少个方法——因为那些东西官方文档都有,查一下就行。为什么需要可变Map?不是因为"它就是Java HashMap的Scala版",而是因为在动态构建数据的场景下,不可变Map的性能不够好。你要在循环里不断往Map里加key-value对,用不可变Map就是O(n²)的灾难,用可变Map就是O(n)的高效。但可变Map也不是万能的。它只适合"构建"场景——你在一个方法内部,动态构建一个Map,最后输出一个不可变Map。

https://starzy1990.github.io/ 360

深入理解Scala元组:从多返回值到模式匹配的桥梁

函数式编程里,函数的参数和元组是一一对应的。在函数式编程里,一个函数可以看成是接收一个参数、返回R的函数。这个叫"函数的元组化"(tupled)。而Scala的类型系统在处理多参数函数的时候,需要为每个参数数量生成对应的函数类型——、…、。因为函数最多到Function22,所以元组也最多到Tuple22。这是一个统一的设计——元组和函数,共享同一个N的上限。那22以上怎么办?用嵌套元组或者case class。// 超过22个元素:用嵌套。

https://starzy1990.github.io/ 699
上一篇: Actors in Scala(Scala中的Actor)(预打印版) 第五章 Event-Based Programming (B)
下一篇: HDFS Federation(HDFS 联盟)介绍
Guibin
博客等级 码龄23年 45粉丝 13原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值