Scala:简单使用Actor的消息发送与接收求和
2010-09-13 21:30
281 查看
从Scala的诸多介绍当中,就看到了不少特别指出Scala中的Actor能够实现并行编程的强大功能,它是基于事件模型[/b]的并发机制。或者说,Scala是运用消息([/b]message[/b])[/b]的发送、接收来实现多线程的。使用Scala能够更容易地实现多线程应用的开发。
说到并行与消息发送、接收,我记起了上学期“并行计算”课程中的实验上机课中,在VC++6.0下使用的MPI机制就是基于消息的发送与接收来实现并行编程的。当初的实验是做得一塌糊涂啊,要不现在学习Scala的Actor基于消息的并行编程机制就不会那么难理解了。可惜…
对于Java,我们都知道它的多线程实现需要对共享资源(变量、对象等)使用synchronized 关键字进行代码块同步、对象锁互斥等等。而且,常常一大块的try…catch语句块中加上wait方法、notify方法、notifyAll方法是让人很头疼的。原因就在于Java中多数使用的是可变状态的对象资源,对这些资源进行共享来实现多线程编程的话,控制好资源竞争与防止对象状态被意外修改是非常重要的,而对象状态的不变性也是较难以保证的。
而在Scala中,我们可以通过复制不可变状态的资源(即对象,Scala中一切都是对象,连函数、方法也是)的一个副本,再基于Actor的消息发送、接收机制进行并行编程。
下面是我刚刚学习到Actor并行编程知识所做的一个模拟程序,虽然相当简单甚至弱智(见怪不怪啊,呵呵…),但总算是自己尝试着理解了《Programming Scala 铅笔书》中的内容写出来的。
程序目的:给定一个Int整数number,使用Actor计算从1到number的总和。代码如下:
其中的 (0 /:[/b] (1 to num)) 等效于 List 中的foldLeft 方法,/:[/b] [/b]只不过是foldLeft方法的一个简洁写法而已。说起来List中的这个foldLeft方法也是花了我好些时间来从试错中理解到的(就是还没习惯理解英文书的讲述,得加强锻炼),特别是foldLeft方法中接下来使用Curring技巧传入参数、函数文本所代表的含义等等。我感觉Scala的语法太简洁以至于有些难理解…+_+
代码中已有部分注释,不过应注意import进scala.actors.Actor 类,其中的self、!(感叹号,发送方法)和receive方法都是Actor类中的方法。我特地不用下划线“_”导入Actor类中的所有方法,而是用显式的Actor加点的形式进行调用。
尝试了不同的输入,程序输出如下:
1、故意给了个超大的整数,运行中内存堆溢出了,刚好被我发现并截图了,OutOfMemoryError:Java heap space 。有趣的是,程序继续在运行,接下来还有更加难理解的错误输出呢,输出太快来不及截图。
这是“疯狂”的CPU和内存使用情况,天啊,我的内存才1 GB,它就耗掉了0.99GB,+_+…
2、这个是输入为100000的运行情况,正常。
其实我还不清楚上面的输出是否正常,或者说我还不知道上面的代码是否合理,因为铅笔书的下一节才是“Message Passing(消息传递)”呢。看上面的输出,很明显并不是按照从 1 到100000 顺序输出的,这是不是Scala消息传递或者说并行编程的效果呢?期待接下去的学习,哈哈…
说到并行与消息发送、接收,我记起了上学期“并行计算”课程中的实验上机课中,在VC++6.0下使用的MPI机制就是基于消息的发送与接收来实现并行编程的。当初的实验是做得一塌糊涂啊,要不现在学习Scala的Actor基于消息的并行编程机制就不会那么难理解了。可惜…
对于Java,我们都知道它的多线程实现需要对共享资源(变量、对象等)使用synchronized 关键字进行代码块同步、对象锁互斥等等。而且,常常一大块的try…catch语句块中加上wait方法、notify方法、notifyAll方法是让人很头疼的。原因就在于Java中多数使用的是可变状态的对象资源,对这些资源进行共享来实现多线程编程的话,控制好资源竞争与防止对象状态被意外修改是非常重要的,而对象状态的不变性也是较难以保证的。
而在Scala中,我们可以通过复制不可变状态的资源(即对象,Scala中一切都是对象,连函数、方法也是)的一个副本,再基于Actor的消息发送、接收机制进行并行编程。
下面是我刚刚学习到Actor并行编程知识所做的一个模拟程序,虽然相当简单甚至弱智(见怪不怪啊,呵呵…),但总算是自己尝试着理解了《Programming Scala 铅笔书》中的内容写出来的。
程序目的:给定一个Int整数number,使用Actor计算从1到number的总和。代码如下:
import scala.actors.Actor def calculateSum(number: Int) = { val num = number val caller = Actor.self // 获得当前线程的引用 for(i <- 1 to num){ Actor.actor{ caller ! { // 调用!发送消息 println(i) // 打印每次发送出去的i i // 发送i,下面receive中case的sumInSent类型为Int } } } // 下句的 /: 等效于List.foldLeft方法 val sum = (0 /: (1 to num)){ (partialSum, elem) => Actor.receive{ // 接收并用case匹配传入的Int值 case sumInSent: Int => partialSum + elem // 统计和 } } println("sum = " + sum) } calculateSum(100000)
其中的 (0 /:[/b] (1 to num)) 等效于 List 中的foldLeft 方法,/:[/b] [/b]只不过是foldLeft方法的一个简洁写法而已。说起来List中的这个foldLeft方法也是花了我好些时间来从试错中理解到的(就是还没习惯理解英文书的讲述,得加强锻炼),特别是foldLeft方法中接下来使用Curring技巧传入参数、函数文本所代表的含义等等。我感觉Scala的语法太简洁以至于有些难理解…+_+
代码中已有部分注释,不过应注意import进scala.actors.Actor 类,其中的self、!(感叹号,发送方法)和receive方法都是Actor类中的方法。我特地不用下划线“_”导入Actor类中的所有方法,而是用显式的Actor加点的形式进行调用。
尝试了不同的输入,程序输出如下:
1、故意给了个超大的整数,运行中内存堆溢出了,刚好被我发现并截图了,OutOfMemoryError:Java heap space 。有趣的是,程序继续在运行,接下来还有更加难理解的错误输出呢,输出太快来不及截图。
这是“疯狂”的CPU和内存使用情况,天啊,我的内存才1 GB,它就耗掉了0.99GB,+_+…
2、这个是输入为100000的运行情况,正常。
其实我还不清楚上面的输出是否正常,或者说我还不知道上面的代码是否合理,因为铅笔书的下一节才是“Message Passing(消息传递)”呢。看上面的输出,很明显并不是按照从 1 到100000 顺序输出的,这是不是Scala消息传递或者说并行编程的效果呢?期待接下去的学习,哈哈…
相关文章推荐
- Scala:简单使用Actor的消息发送与接收求和
- QUdpSocket简单使用Demo(局域网内发送给所有客户端消息与接收)
- Scala Actor,receive不断接收消息,react复用线程,结合case class的actor,Future使用,使用Actor进行wordCount
- 使用RabbitMQ简单发送接收消息
- rabbitMQ学习笔记(二) 简单的发送与接收消息 HelloWorld
- 【Spring】使用Spring和AMQP发送接收消息(下)
- 【翻译】使用Scala和Akka Actor发送邮件
- Android 使用EventBus发送消息接收消息
- 如何使用C#和VB发送和接收MSMQ消息
- Android非UI主线程中,若干普通Java线程使用Handler发送接收消息
- Java Socket发送与接收HTTP消息简单实现
- 安卓 handler的使用 发送消息 , 接收消息(做相应的操作)
- Java Socket发送与接收HTTP消息简单实现
- MFC Dialog工程中多线程使用PostMessage发送接收字符串消息并更新界面
- scala-akka实现简单的分布式RPC通信框架(主从监听,消息发送)
- C#简单实现自定义消息的发送和接收
- RabbitMQ第一篇——初识RabbitMQ,简单的消息发送和接收
- ActiveMQ实例1--简单的发送和接收消息
- .Net下RabbitMQ的使用(2) -- 发送接收消息
- C#TCPClient应用-一个简单的消息发送和接收