scala笔记和akka笔记

来源:互联网 发布:北京圆之翰大数据 编辑:程序博客网 时间:2024/06/06 10:16

应用层

  • 80/20原则:80%的代码是 纯函数,其余如处理IO,数据库,用户交互等方面的20%的代码也应该尽量轻量级
  • 培养面向表达式的编程思维,培养函数式编程思维
  • 用Actor模型实现并发功能
  • 将更多的 行为 从 类里 移到 更细粒度的 trait中

代码层

  • 坚持写纯函数
  • 习惯将函数作为变量和参数进行传递
  • 重点学习scala的集合类和其API
  • 尽量使用immutable代码,优先使用val和immutable集合
  • 使用Option/Some/None/  忘记 java null的概念
  • 使用 try/Success/Failure类
  • 使用一种TDD/BDD 测试工具如 ScalaTest 或 specs2
  • 使用SBT来构建项目
  • 编码时 打开一个Scala的REPL控制台,随时测试验证的你的想法

纯函数-没有副作用的代码段

  • 引用透明性:同样的输入参数,总是返回同样的结果!
  • 表达式的值没有依赖应用的某个 状态|值|IO,只依赖输入参数和计算算法
  • 无副作用:函数不应该带来对应用的某个 状态|值 的mutable
  • 不会对输入参数进行 改变 mutable
  • 不执行IO操作或者和用户进行交互

纯函数实例

  • 数学计算方法,如 + -  *
  • String的 split、length、to* 方法
  • immutable集合上的方法, 如map、drop、take、filter flatMap
  • 从HTML字符串中 抽取值的方法,模式匹配

非纯函数-带副作用的

  • getDayOfWeek    getHoure  getMinute
  • getRandomNumber
  • 读取用户输入的、或打印输出的  方法
  • 向存储器 读写 数据的 方法

Java程序中一般很多:字段通常是 mutable的;类似set方法mutable了类内部的字段,而get方法则可能返回 可mutable的数据结构

分析java源码 然后慢慢重构为 Scala化的 代码  善用 case class和 object单例对象

尽量使用immutable对象

尽量优先使用immutable集合和val 变量

private val varname = new MutableObject

如让外部有直接操作或改变内部对象的权利

面向表达式的编程Expression Oriented Programming

面向表达式的编程指每一语句都是一个表达式,有返回值,无副作用, 函数式编程语言都应该这样!

相对的statement编程是不返回数据,使用副作用!

scala中的if/else match/case  try/catch 都有返回值

优点:更易理解的代码;没副作用,更容易测试;与scala语法绑定;更适合多核计算机

使用match/case来模式匹配

使用场景:

  • try catch
  • 函数或方法的主体中
  • Option Some None 代码模式中
  • actor的receive中
  • 替代笨拙的 if else if else    switch/case
  • 模式匹配中 case class
  • 部分函数中

忘记java中null的概念禁止使用null

变量初始化用Option   参数使用Option

没有获取预期的结果时 返回Option|None而非null,

用try  success failure 范式来返回错误信息

函数或方法不要返回 null,返回Option或者 try替代

将第三方包返回的null转换为Option

从Option获取值

同时使用Option 和集合   map flatten flatMap  collect

Try/Success/Failure提供更好的处理方式:filter flatMap flatten foreach map    get  getOrElse orElse  toOption  recover recoverWith transform




非阻塞的程序 应该保障的一些特性

  • 等待无关性wait-free:能确保每次的调用在有限的步数之内完成,不管其他调用的步骤有多少。杀掉几个线程
  • 锁无关性lock-free:执行这段程序的某些线程会被延迟,但必须确保至少有一个线程能持续步骤到执行完毕。这一点需防止可能出现的饿死,就是说防止某个线程永远被延迟。
  • 阻碍阻塞无关性obstruction-free:有个时间点,在这个点之后非阻塞方法独立的在有限次步骤内执行完毕
  • 锁无关的程序一定是阻碍无关的,反之不一定。
  • 乐观并行控制法是障碍阻塞无关的,当检测到有冲突时,回滚修改,然后接受某种调度策略,过一会再试。

 

如果不得不进行阻塞操作,如线程sleep不确定的一段时间、等待时间发生,rdbms驱动,消息APi,IO,放到 future中很简单,但是可能带来性能问题和OOM。处理阻塞问题的解决方法:

将阻塞调用放到一个或管理一组actor的router中。确保配置一个线程池

将阻塞放到Future中时一定要确保对这个Future的调用是有上限的,否则容易oom。也可以配置带上限的线程池

使用单个线程来管理一组阻塞的资源,通过actor的消息分发出事件。

 

Actor容器人

ActorRef

State  可序列化  和还原

Behavior

MailBox

默认是先进先出的队列,可以自行实现优先级队列,但akka中当前behavior必须总是处理下一个出队的消息,而且没有扫描mailbox的动作,处理消息失败时,即认为failure发生了,当然这个行为可以被重写

is Supervisor  ,can create许多Children,创建和停止都是异步的,马上返回,请记住!

监控策略也就是失效处理机制

上级将任务委托给下级 进行执行,监督的层级

                        root

/user                                               /system

自定义的                                          系统支持的

一对一监督,OneForOneStrategy

多对一监督,AllForOneStrategy,一个Actor的失效会影响同组同辈的Actor失效时,适用

重启时,不会清空mailbox

 

Actor的路径和地址路由

不同类型的ActorReferences

纯本地Actor Ref,不能跨网络发送消息到远程的jvm上

开启远程功能的本地Actor Ref,带有protocol和远程地址信息

router型本地Actor Ref,消息直接发给其children

远程Ref ,序列化的消息传送

PromiseActorRef

DeadLetterActorRef

EmptyLocalActorRef

用不到但存在的:root的监测这the one pseudo-supervisor

Logging.StandarOutLogger

 

Actor实例化

不要在一个Actor中申明另一个Actor

不要传递Actor的this 指针到Props

Props是一个配置工具类,用来配置创建Actor时所需的信息,如参数和类名

为每个Actor提供一个Props的工厂,来新创actor

建议actor的层级结构来支持failure处理

path和UID代表一个actor,重启时 path和UID不会变

 

MessgeDispatchers是akka系统的引擎,同时也是ExecutionContext执行上下文环境

,可以用来执行任何代码

ActorSystem都有个默认的可配置的dispatcher

fork-join-executor   thread-pool-executor

四种类型的dispatcher来新建actor或者说线程

Dispatcher:默认的,事件驱动的,将一组actor绑到一个线程池中,共享线程的,

PinnedDispatcher:一个actor一个线程,线程不共享,

BalancingDispatcher:事件驱动的,会将任务繁重的actor的一些任务分发到 空闲的actor上,所有actors共享一个mailbox,前提是这些actor的所有实例都能处理 mailbox中的消息,不能用作Router Dispatcher

CallingThreadDispatcher:仅在当前线程 执行 invocations,不新建线程,可由不同线程对同一个actor进行调用,适于测试

 

MailBox信箱

按以下步骤确定mailbox的类型:

1、以 actor的deployment配置中的mailbox项为准,否则

2、以 actor的Props包含mailbox的配置,(如withMailbox)为准,否则

3、以 actor的Dispatcher配置中mailbox-type为准,否则

4、以actor包含的mailbox type为准,如with RequiresMessageQueue[BoundedMessageQueueSemantics],否则

5、以 actor的 Dispatcher包含的mailbox type为准,否则

6、默认为akka.actor.default-mailbox(无限邮箱,Java.util.concurrent.ConcurrentLinkedQueue,SingleconsumerOnlyUnboundedMailbox是个更高效的信箱,但不能用于BalancingDispatcher)

实现MailboxType[ActorSystem.Settings, Config]即可自定义信箱,Akka自带实现的信箱类型有akka.dispatch.:

UnboundedMailbox-java.util.concurrent.ConcurrentLinkedQueue,非阻塞,无限消息,unbounded

SingleConsumerOnlyUnboundedMailbox-一个高效的多生产者单消费者队列,非阻塞,无限消息

BoundedMailbox-java.util.concurrent.LinkedBlockingQueue,阻塞,有限消息,bounded

UnboundedPriorityMailbox-java.util.concurrent.PriorityBlockingQueue,阻塞,无限消息

BoundedPriorityMailbox-由akka.util.BoundedBlockingQueue封装的java.util.concurrent.PriorityBlockingQueue,阻塞,有限消息

 

 

消息路由Routing    routeees

akka自带的路由规则器有:akka.routing.

akka.routing.RoundRobinRoutingLogic

akka.routing.RandomRoutingLogic 
• akka.routing.SmallestMailboxRoutingLogic 
• akka.routing.BroadcastRoutingLogic 
• akka.routing.ScatterGatherFirstCompletedRoutingLogic 
• akka.routing.ConsistentHashingRoutingLogic

 

 

case class 、object中case的作用,生成大量模板代码

,使用case的class会自动生成如下:

apply方法:无需使用new来新建对象了,

给构造函数的参数(默认为val的)自动创建了 get 方法,如果参数申明为 var则自动生成get/set方法了

toString, equals ,hashCode, copy方法

unapply: 方便用于 match表达式中

case class的目标是创建不可变 记录,以更好地用于模式识别

 

链式调用

返回:this.type可实现链式调用,如果是不能被继承的类则方法最后直接返回 this亦可

 

method 方法   function 函数

def methodname(arg: Type,  funcname(argn: Type)  =>Type){

}

输入   =>   输出     =>映射 转换 

val funcname = (argn: Type1) : Type2 =>{   ….     Type2 }

method不能作为参数传递,而 function可以,function就是个函数类型的 变量

function函数是一个对象,继承自trait: Function0, Function1, …… Function22

部分函数

函数式编程思想: 将函数apply到参数上面

java中是对参数 进行全函数处理

而Scala中可以只传入部分参数,函数进行部分处理,偏函数

将一个多参数函数的一部分参数赋值,而另一部分作为新 函数的  参数的方法

不是一一映射  部分映射而已,不能对所有输入进行处理,过滤掉一部分输入

PartialFunction[InputargsType, ReturnType] = {   。。。。。。   }

Scala集合

明确: 预测器:predicate是个返回boolean的 函数或方法

匿名函数: ()  => { …….. }

隐式loop:集合方法filter foreach map reduceLeft …都能隐式的对元素进行for循环

集合层级

顶级的三层trait:始于 Traversable 中间 iterable ,然后三分天下: Seq  Set  Map

以这三个 散枝阔叶出庞大的集合系

`[Y{19(DC%GQ]HOM0Z)D_[R

序列最好用不可变的vector   或者可变的arraybuffer

J7O6U`~(_%GRDDVYU4`~BFJ

 

DB6~N9YGZFHHQKCSWK%}T}6

map

其他看起来像集合的类

枚举enumeration:有限集合    iterator:提供很多遍历方法   option:处理null的有效工具        tuple元祖:异种数据集合

当集合元素数量很大时,需要使用lazy集合而不是strict 集合,内存没这么大 :使用集合的view方法

scala中 :结尾的方法是 从右向左 估值的

0 0
原创粉丝点击