阅读背景:

scala(4)

来源:互联网 
1.并发编程模型Akka
1.1. Akka 介绍
多线程开发要处理并发,锁,线程同步等一系列问题,一不小心,弄个大的bug,所以一般都不愿意自己动手写,能不能换一种思路,可以不可以搞一种更高级的抽象模型,让我想实现多线程应用的时候,不用再考虑这些底层问题呢?
Akka是JVM平台上构建高并发、分布式和容错应用的工具包和运行平台。Akka是用 Scala语言编程的一个并发编程框架,该框架基于Actor编程模型。 
Akka实现并发,基于Actor模式,
相当于Java实现并发,基于Thread。

1.2.Akka中Actor模型
与java的基于共享数据和锁的线程模型不同,scala的actor包则提供了另外一种不共享任何数据、依赖消息传递的模型。
在基于Actor的系统里,所有的事物都是Actor,就好像在面向对象设计里面所有的事物都是对象一样。但是有一个重要区别,那就是Actor模型是作为一个并发模型设计和架构的,而面向对象模式则不是。Actor与Actor之间只能通过消息通信。

可以将Actor当作是一群人,他们互相之间不会面对面地交流,而只是通过邮件的方式进行沟通。传递消息是actor模型的基础。


Actor是一种编程模型,通过发送消息的方式实现并发编程
必须有多个相同业务逻辑的Actor才可以实现并发编程,一个Actor相当于一个实例(老师/学生),消息是发送的数据(邮件)
Actor和Actor之间可以相互发送消息
每一个Actor中都有相应的业务逻辑,如果使用编程,定义一个类,在类中定义方法,通过new一个实例,即可得到一个Actor
Actor是ActorSystem创建的,ActorSystem的职责是负责创建并管理自己创建的Actor,ActorSystem的单例的,一个JVM进程中有一个即可,而Acotr是多例的。ActorSystem相当于老大,Actor相当于干活的小弟
1.3.使用Actor模型的好处:
事件模型驱动--Actor之间的通信是异步的,即使Actor在发送消息后也无需阻塞或者等待就能够处理其他事情;
强隔离性--Actor中的方法不能由外部直接调用,所有的一切都通过消息传递进行的,从而避免了Actor之间的数据共享,想要观察到另一个Actor的状态变化只能通过消息传递进行询问;
轻量性--Actor是非常轻量的计算单机,单个Actor仅占400多字节,只需少量内存就能达到高并发;
Java内置线程模型	Scala actor模型
“共享数据-锁”模型(share data and lock)	share nothing
每个object有一个monitor,监视多线程对共享数据的访问	不共享数据,actor之间通过message通信
加锁的代码段用synchronized标识	 
死锁问题	 
每个线程内部是顺序执行的	每个actor内部是顺序执行的


1.4.maven工程:
如果本地仓库的jar包没有下载成功,就有一个.lastUpdate为后缀的文件,删除该文件,然后重新下载。

1.4.1.IDEA中配置maven
默认加载本机的maven目录,所以正常不用配置

1.4.2.创建maven工程



1.4.3.Pom依赖:
完整参考pom.xml文件
<!-- 定义一下常量 -->
<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <encoding>UTF-8</encoding>
    <scala.version>2.11.8</scala.version>
    <scala.compat.version>2.11</scala.compat.version>
    <akka.version>2.4.17</akka.version>
</properties>


<dependencies>
    <!-- 添加scala的依赖 -->
    <dependency>
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-library</artifactId>
        <version>${scala.version}</version>
    </dependency>

    <!-- 添加akka的actor依赖 -->
    <dependency>
        <groupId>com.typesafe.akka</groupId>
        <artifactId>akka-actor_${scala.compat.version}</artifactId>
        <version>${akka.version}</version>
    </dependency>

    <!-- 多进程之间的Actor通信 -->
    <dependency>
        <groupId>com.typesafe.akka</groupId>
        <artifactId>akka-remote_${scala.compat.version}</artifactId>
        <version>${akka.version}</version>
    </dependency>

</dependencies>
   

配置:


如果按照外部的maven
1,解压安装包
2,修改环境变量,    M2_HOME=      把%M2_HOME%\bin 添加到Path中。
3,在cmd窗口中,使用mvn -version   里查看配置的环境变量是否生效


如果把settging.xml文件添加到了 用户/.m2目录下,
可以修改本地仓库。

修改为自己指定的目录即可。
<localRepository>/path/to/local/repo</localRepository>

本地仓库: 
作用: 
存放maven工程下载的依赖jar包。
当我们配置好了一个依赖jar包之后:
<dependency>
    <groupId>org.scala-lang</groupId>
    <artifactId>scala-library</artifactId>
    <version>${scala.version}</version>
</dependency>


maven就会首先去本地仓库中找,没找到就去找镜像(远程仓库),如果该远程仓库也没有,就去maven的中央仓库找。

一旦找到之后,就会把该jar包以及该jar包的所有依赖jar包通通下载到本地仓库。


<mirrors>
    <mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
      <url>https://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>        
    </mirror>
  </mirrors>

使用maven工作时,
使用的是生命周期方法,


这些生命周期方法,是抽象的,具体干活的小弟,是插件。
插件只需要添加进pom文件即可, 不需要关注底层的工作。

maven工程,输出目录:target
最常用的生命周期方法:
clean: 清除工作目录。
package:打包 生成jar包

clean  + package    一起使用
install: 把自己的项目达成jar包,然后发布到本地仓库中。

如果jar包最终的目录中,存在以.lastUpdate 为后缀的文件,记得要删除掉,然后重新下载。



1.5.案例1:Actor入门案例
一个Actor就是一个类,要想实现actor功能,需要实现Actor特质
需要重写receive方法,进行消息匹配接收

程序运行需要执行入口,所以需要有main方法。
actor必须通过ActorSystem来创建

// 通过字符串添加配置信息
    val str =
      """
        |akka.actor.provider = "akka.remote.RemoteActorRefProvider"
        |akka.remote.netty.tcp.hostname = "127.0.0.1"
        |akka.remote.netty.tcp.port = "8888"
      """.stripMargin
// 创建配置工厂
    val conf = ConfigFactory.parseString(str) 
    // 创建actorsystem
    val as: ActorSystem = ActorSystem.create("actorsystem-test",conf)
    // 通过类型反射创建actor的引用对象
    val actor: ActorRef = as.actorOf(Props[HelloActor],"actor-test")
// 向actor引用对象发送异步消息
actor ! "hello"



1.6.案例 人机Ping Pang大战
思路:
需要两个Actor,通过发送消息进行通信。
一个Actor在启动时,需要向另一个actor发送连接请求。
连接请求在preStart()方法中实现。



class AlphGo extends Actor{
  // 表示接受的方法,进行模式匹配 会被调用多次
  override def receive: Receive = {
      }
}

object AlphGo{
  def main(args: Array[String]): Unit = {
  }
}


class MaLong extends Actor{
  // 在构造器之后,receive方法之前执行
  override def preStart(): Unit = {
    // worker向master建立连接,并向master发送消息
// 四个关键参数: actorSystem的名称  actor的名称   ip地址,端口号
    val proxy: ActorSelection = context.actorSelection("akka.tcp://1.并发编程模型Akka
1.1. Akka 介绍
多线程开发要处理并发,锁,线程



你的当前访问异常,请进行认证后继续阅读剩余内容。

分享到: