回顾
object 回顾 {
/**
* 类
* 类的定义: class ClassName()
* 类后面的括号,类的主构造器(val name: String, var age: Int)
* val(get) | var(get|set)
*
* 类的辅助构造器 def this(构造参数...)在辅助构造器中必须先调用类的主构造器
*
* 类的构造器访问权限 private[] (构造器)
*
* 类的访问权限 private[this] class ClassName:在当前包可见
* private[包名] class ClassName:在当前包和子包下都可见
*
*
* 对象
* object 定义的对象是单例对象,对象中的方法和属性都是静态的
*
* 伴生对象:
* objectName 和 className的名称一致,并且在同一个scala源文件中,这个objectName叫做这个class的伴生对象
* class叫做这个object的伴生类
* 伴生类和伴生对象可以互相访问私有的成员和方法
* 注意:private[this] 修饰的不能访问
*
* apply方法
* objectName.apply()和objectName()是一样的效果
*
*
* 特质
* 定义特质使用Trait关键字
* 特质相当于Java中的Interface,但是比Java中的Interface更强大一些,因为在trait中可以定义有具体实现的方法
* 或者定义没有任何实现的方法
*
* 类或对象可以动态的混入特质,并且可以同时混入多个特质
*
* 如果某个类或对象(继承)混入了某个特质,这个特质有一个没有实现的方法A,还有一个带有实现方法的方法B,
* 这个类或者对象必须实现这个没有实现的方法A,可以重写方法B,必须使用override关键字
*
* 混入多个特制的时候,使用with关键字
*
* 抽象类
* 定义抽象类使用abstract
*
* 在Scala中继承抽象类的话,必须使用extends关键字
*
* 样例类,样例对象
* 样例类定义使用:case class ClassName(属性)
* 样例对象:case object ObjectName
* 默认实现了serializable,Product
* 支持模式匹配
*
* 模式匹配
* 类似Java中的 switch case,但是比Java中的更强大
*
* val xx = var|val match{
* case /字符串/类型/集合/Tuple/样例类/样例对象 if 守卫 => Any
*
* }
*
*
*
*/
}
1.并发编程模型Akka
Akka是JVM平台上构建高并发发,分布式和容错应用的工具包和运行时。Akka用Scala语言写成,同时提供了scala和java的开发接口。
Akka处理并发的方法基于Actor模型。在基于Actor的系统里,所有的事物都是Actor,好象在面向对象设计里面所有的事物都是对象是一样。
区别:Actor模型是作为一个并发模型设计和架构的,而面向对象则不是。Actor与Actor之间只能通过消息通信。
优点:1.对并发模型进行了更高的抽象
2.异步,非阻塞,高新能的事件驱动编程模型
3.轻量级事件处理
Actor工作机制

1>在Akka的pom.xml文件中引入依赖
<!-- 定义一下常量 -->
<properties>
<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>
<!-- 指定插件-->
<build>
<!-- 指定源码包和测试包的位置 -->
<sourceDirectory>src/main/scala</sourceDirectory>
<testSourceDirectory>src/test/scala</testSourceDirectory>
<plugins>
<!-- 指定编译scala的插件 -->
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.2.2</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
<configuration>
<args>
<arg>-dependencyfile</arg>
<arg>${project.build.directory}/.scala_dependencies</arg>
</args>
</configuration>
</execution>
</executions>
</plugin>
<!-- maven打包的插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>reference.conf</resource>
</transformer>
<!-- 指定main方法 -->
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>cn.sheep.robot.ClientActor</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
2>案例–HelloActor
class HelloActor extends Actor{
//接受消息的
override def receive: Receive = {
//接受消息并处理
case "你好帅" => println("竟说实话,呵呵")
case "丑" => println("滚犊子")
case "stop" => {
context.stop(self) //将自己停止
context.system.terminate() //关闭自己的工厂
}
}
}
object HelloActor{
private val nBFactory = ActorSystem("NBFactory") //工厂
private val helloActorRef: ActorRef = nBFactory.actorOf(Props[HelloActor], "helloActor")
def main(args: Array[String]): Unit = {
//给自己发送消息
helloActorRef ! "你好帅"
helloActorRef ! "丑"
helloActorRef ! "stop"
}
}
3.案例–龙哥大战峰哥
/**
* 马龙
*/
class LongGeActor(val fg: ActorRef) extends Actor{
override def receive: Receive = {
case "start" => {
println("龙龙:I'm OK")
fg ! "啪"
}
case "啪啪" => {
println("你真猛")
Thread.sleep(1000)
fg ! "啪"
}
}
}
/**
* 高峰
*/
class FengGeActor extends Actor{
override def receive: Receive = {
case "start" => println("峰峰说:I'm OK")
case "啪" => {
println("峰峰说:我可以!")
Thread.sleep(1000)
sender() ! "啪啪"
}
}
}
object PingPongApp extends App {
//actorSystem
private val pingPongActorSystem = ActorSystem("PingPongActorSystem")
//通过actorSystem创建ActorRef
private val ffActorRef = pingPongActorSystem.actorOf(Props[FengGeActor], "ff")
//创建LongGeActorRef
private val mmActorRef = pingPongActorSystem.actorOf(Props(new LongGeActor(ffActorRef)), "mm")
ffActorRef ! "start"
mmActorRef ! "start"
}
4.案例–智能机器人解答疑问
package cn.sheep.robot
import akka.actor.{Actor, ActorSystem, Props}
import com.typesafe.config.ConfigFactory
import scala.io.StdIn
class EduAynuServer extends Actor{
//用来接受客户端发送过来的问题
override def receive: Receive = {
case "start" => println("老娘以就绪!")
case ClientMessage(msg) => {
msg match {
case "你叫啥" => sender() ! ServerMessage("铁扇公主")
case "你是男是女" => sender() ! ServerMessage("老娘是男的")
case "你有男票吗" => sender() ! ServerMessage("没有")
case _ => sender() ! ServerMessage("What you say?") //sender()发送端的代理对象,
}
}
}
}
object EduAynuServer extends App{
val host: String = "127.0.0.1"
val port: Int = 8001
val config = ConfigFactory.parseString(
s"""
|akka.actor.provider = "akka.remote.RemoteActorRefProvider"
|akka.remote.netty.tcp.hostname = $host
|akka.remote.netty.tcp.port = $port
""".stripMargin)
//指定ip和端口号
private val actorSystem = ActorSystem("Server", config)
private val serverActorRef = actorSystem.actorOf(Props[EduAynuServer], "shanshan")
serverActorRef ! "start"
}
package cn.sheep.robot
//服务端发送给客户端的消息格式
case class ServerMessage(msg: String)
//客户端发送给服务器端的消息格式
case class ClientMessage(msg: String)
package cn.sheep.robot
import akka.actor.{Actor, ActorSelection, ActorSystem, Props}
import cn.sheep.robot.EduAynuServer.{host, port}
import com.typesafe.config.ConfigFactory
import scala.io.StdIn
class ClientActor extends Actor{
var serverActorRef: ActorSelection = _ //服务端的代理对象
override def preStart(): Unit = {
serverActorRef = context.actorSelection("akka.tcp://Server@127.0.0.1:8001/user/shanshan")
}
override def receive: Receive = {
case "start" => println("牛魔王系列已启动!")
case msg: String => {
serverActorRef ! ClientMessage(msg)
//把客户端输入的内容发送给 服务端(actorRef)-->服务端的mailbox中 --> 服务端的receive
}
case ServerMessage(msg) => println(s"收到服务端消息:$msg")
}
}
object ClientActor extends App{
val host: String = "127.0.0.1"
val port: Int = 8003
val config = ConfigFactory.parseString(
s"""
|akka.actor.provider = "akka.remote.RemoteActorRefProvider"
|akka.remote.netty.tcp.hostname = $host
|akka.remote.netty.tcp.port = $port
""".stripMargin)
private val clientSystem = ActorSystem("client", config)
//创建了dispatch | mailbox
private val actorRef = clientSystem.actorOf(Props[ClientActor], "NMW-02")
actorRef ! "start" //发送到自己的MailBox里面
while (true){
val quession = StdIn.readLine()
actorRef ! quession
}
}
5.Actor通信模型

6.服务器与客户端交互过程

7.服务器与客户端交互详解

8.Spark Master 和 Worker 通信机制

博客主要回顾了Scala语言下的并发编程模型Akka。Akka是JVM平台构建高并发、分布式和容错应用的工具包与运行时,基于Actor模型处理并发,具有对并发模型抽象度高、异步非阻塞等优点,还介绍了其工作机制及多个案例,以及通信机制。
1454

被折叠的 条评论
为什么被折叠?



