zoukankan      html  css  js  c++  java
  • geotrellis使用(六)Scala并发(并行)编程

          本文主要讲解Scala的并发(并行)编程,那么为什么题目概称geotrellis使用(六)呢,主要因为本系列讲解如何使用Geotrellis,具体前几篇博文已经介绍过了。我觉得干任何一件事情基础很重要,就像当年参加高考或者各种考试一样,老师都会强调基础,这是很有道理的。使用Geotrellis框架的基础就是Scala和Spark,所以本篇文章先来介绍一下Scala编程语言,同样要想搞明白Scala并发(并行)编程,Scala基础也很重要,没有Scala语言基础就谈不上Scala并发编程也就更谈不上使用Geotrellis或者Spark,本文先简单介绍一下Scala基础知识,这方面的书籍或者文章很多,大家可以网上找一下。

    一、Scala基础     

          关于Scala基础最主要的就是模式匹配,这造就了整个Scala语言灵活方便的特点,通俗的说模式匹配就是其他语言中的switch case,但是其实功能要远远复杂的多,涉及到样本类(case class)、unapply函数等具体网上有很多介绍。其次还有强大的for表达式、偏函数、隐式转换等,下面主要为大家介绍Scala并发(并行)编程。

    二、SBT简介    

          使用Scala语言编程,最好使用SBT框架,可以自动帮你完成包管理等,相当于java中的maven,下面先简单介绍一下SBT基础。

          首先安装SBT,很简单,只需要下载安装包即可(http://www.scala-sbt.org/release/docs/Installing-sbt-on-Windows.html),具体安装过程以及配置等,大家也可以在网上找的到。安装完成之后,在IDEA中安装sbt插件,然后选择创建SBT项目,与普通Scala语言最主要的不同是会创建一个build.sbt文件,这个文件主要记录的就是项目的依赖等,要添加依赖就可以添加如下两行代码:

    libraryDependencies +=  "com.typesafe.akka" % "akka-actor_2.11" % "2.4.4"
    
    resolvers += "Akka Snapshot Repository" at "http://repo.akka.io/snapshots/"

          其实build.sbt文件是一个被SBT直接管理的scala源文件,里面的语句均要符合Scala语法,其中libraryDependencies和resolvers 是定义好的Key,+= % at等都是写好的方法。libraryDependencies是存储系统依赖的Key,该语句添加了一个ModuleID对象,"com.typesafe.akka"为groupID,"akka-actor_2.11"为artifactID,2.4.4"为revision,%方法最终就创建了一个ModuleID对象,此处需要注意_2.11表示当前的Scala版本。resolvers表示系统如何能够找到上面的libraryDependencies,at 方法通过两个字符串创建了一个 Resolver 对象,前者为名称,后者为地址。一般lib的官网中均会有写明自己的上述语句供使用者方便添加自己lib依赖。

    三、并发编程     

         下面为大家介绍如何使用Scala进行并发编程。

    1、原生支持

         Scala语言原生支持并发编程,只需要使类继承scala.actors.Actor即可,复写父类的act方法,也可以直接建立一个匿名类,直接使用actor{}即可,其中receive是一个偏函数,用于接收并处理其他Actor发送的消息,这里就用到了模式匹配,可以根据不同的消息类型进行不同的处理,相当于路由。

     1 object ActorTest2 extends App {
     2   val actor_a: Actor = actor{
     3     while (true){
     4       receive {
     5         case msg => println("actor_a   " + msg)
     6       }
     7     }
     8   }
     9 
    10   val actor_b = actor{
    11     while (true){
    12       receive {
    13         case msg => {
    14           println("actor_b   " + msg)
    15           actor_a ! "b  ---- >>>  a" 
    16           sender ! "receive  " + msg
    17         }
    18       }
    19     }
    20   }
    21 
    22   actor_a ! "wsf"
    23   actor_b ! Math.PI
    24 }

          上面的代码定义了两个Actor对象actor_a,actor_b,采用此种方式Actor会自动start,然后在主线程中各向每个Actor发送了一条信息,Actor接收到信息后进行简单的打印操作。由于Scala已经废弃了此种方式来进行并发编程,在这里也只是简单介绍,下面我们来看一下如何通过使用akka来进行并发编程。

    2、akka

          akka是一个简单易用的Scala并发编程框架(网址:http://akka.io/),其宗旨就是"Build powerful concurrent & distributed applications more easily."。引入akka只需要在build.sbt文件中添加在SBT操作一节中介绍的代码即可,但是要根据自己的Scala版本以及要使用的akka版本进行修改。添加完之后IDEA会自动去下载akka的actor包。其使用基本与原生actor相同,同样创建一个类继承akka.actor.Actor,复写其receive方法。其代码如下:

    1 class MyActor extends Actor{
    2   override def receive={
    3     case message: String=> println(message)
    4     case _ => unhandled()
    5   }
    6 }

          与原生Actor不同的是akka为其Actor加入了path的概念,即每个Actor都有一个绝对路径,这样系统首先要创建一个system,然后在system创建其下的Actor,代码如下:

    val system = ActorSystem("akkatest")

    val actor = system.actorOf(Props(classOf[wsf.akkascala.MyActor]), "akkaactor")

          其中ActorSystem("akkatest")即创建一个akka的system,用于管理Actor,第二句就是在system中创建一个上面MyActor实例。通过打印actor.path可以得到akka://akkatest/user/akkaactor,可以看出该Actor确实是在system之下,其中user表示是用户自定义Actor。

          Actor实例创建之后无需start,会自动启动,可以使用actor ! "hello actor"语句来向actor发送消息,MyActor的receive方法接收到该语句之后进行模式匹配,如果能够匹配上就行进行相应的处理。

          由于Actor具有了路径,其也就能够创建属于自己的Actor实例,只需要在当前Actor类中添加如下代码:

    val otherActor = context.actorOf(Props(classOf[OtherActor]), "otheractor")

          其中OtherActor是定义好的另一个Actor,打印otherActor.path可以得到如下效果:akka://akkatest/user/akkaactor/otheractor,这就表明确实在MyActor中创建了一个子Actor。MyActor就可以管理OtherActor的实例。

          以上介绍了akka的并发编程,其并行编程要稍作修改。

          首先建立一个RemoteActor项目,将build.sbt中项目的引用改为libraryDependencies ++= Seq("com.typesafe.akka" % "akka-actor_2.11" % "2.4.4","com.typesafe.akka" % "akka-remote_2.11" % "2.4.4"),可以看出相比普通Actor项目只是添加了一个akka-remote引用。然后新建一个RemoteActor类同样继承自Actor,与普通Actor毫无区别。然后创建一个主类启动该Actor。唯一需要注意的就是要在resources文件夹中新建一个application.conf文件,该文件是系统的配置文件,里面添加如下代码:

     1 akka {
     2   loglevel = "INFO"
     3   actor {
     4     provider = "akka.remote.RemoteActorRefProvider"
     5   }
     6   remote {
     7     enabled-transports = ["akka.remote.netty.tcp"]
     8     netty.tcp {
     9       hostname = "127.0.0.1"
    10       port = 5150
    11     }
    12     log-sent-messages = on
    13     log-received-messages = on
    14   }
    15 }

          主要定义使用tcp协议的方式进行数据传输,端口是5150。这样就完成了remoteActor的定义。

          然后新建一个LocalActor项目,同样修改build.sbt文件中的内容如上,然后新建一个LocalActor类,由于此处需要向RemoteActor发送消息,所以必须建立一个RemoteActor的子Actor,具体命令如下:

    val remoteActor = context.actorSelection("akka.tcp://remoteSys@127.0.0.1:5150/user/remoteactor")

         其中akka://remoteSys/user/remoteactor是RemoteActor通过system创建的路径,此处与之不同的是akka后添加.tcp表示通过tcp方式创建然后就是remoteSys后通过@127.0.0.1:5150指定远程actor的IP地址以及端口。这样就可建立一个remoteActor的实例,可以通过该实例向remoteActor发送消息。

         LocalActor中也需要添加application.conf文件,但是只需要添加如下语句即可:

    1 akka {
    2   actor {
    3     provider = "akka.remote.RemoteActorRefProvider"
    4   }
    5 }

    四、总结

          本文为大家简单介绍了scala基础、sbt简单操作、原生actor、akka的并发以及并行方式actor,这些是我在学习Geotrellis的过程中学习基础知识的一部分经验总结和梳理,只有打好基础才能更好的拓展自己的知识。要知其然并知其所以然。明白了这些对阅读Geotrellis源代码以及Spark源代码都会有很大的帮助。

    五、参考链接

    一、geotrellis使用初探
    二、geotrellis使用(二)geotrellis-chatta-demo以及geotrellis框架数据读取方式初探
    三、geotrellis使用(三)geotrellis数据处理过程分析
    四、geotrellis使用(四)geotrellis数据处理部分细节
    五、geotrellis使用(五)使用scala操作Accumulo
    六、geotrellis使用(六)Scala并发(并行)编程
  • 相关阅读:
    OLAP ODS项目的总结 平台选型,架构确定
    ORACLE ORA12520
    ORACLE管道函数
    ORACLE RAC JDBC 配置
    ORACLE RAC OCFS连接产生的错误
    ORACLE 启动和关闭详解
    OLAP ODS项目的总结 起步阶段
    ORACLE RAC 配置更改IP
    ORACLE RAC OCR cann't Access
    ORACLE RAC Debug 之路 CRS0184错误与CRS初始化
  • 原文地址:https://www.cnblogs.com/shoufengwei/p/5497208.html
Copyright © 2011-2022 走看看