zoukankan      html  css  js  c++  java
  • scala笔记和akka笔记

    应用层

    • 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中 :结尾的方法是 从右向左 估值的

    正因为当初对未来做了太多的憧憬,所以对现在的自己尤其失望。生命中曾经有过的所有灿烂,终究都需要用寂寞来偿还。
  • 相关阅读:
    面向对象的三个基本特征 和 五种设计原则
    break和continue的区别
    为什么数组是从0开始的
    在线编程挑战网站列表
    十分钟搞清字符集和字符编码
    MMM和MHA的对比和应用(PPT分享)
    MySQL工具汇总
    关于全局唯一ID生成方法
    关于4K Block Size的Device和 Aligned IO
    加快MySQL逻辑恢复速度的方法和参数总结
  • 原文地址:https://www.cnblogs.com/candlia/p/11920335.html
Copyright © 2011-2022 走看看