scala并发编程第八章4-7题

这个代码量有点多,所以分为两篇文章在写

4

使用Actor对象实现ExecutionContext接口
分析:
ExecutionContext接口主要是接收一个Runnable对象,并执行这个Runnable对象,而且也能进行Shutdown service

package com.linewell.chapter8

import akka.actor.{Actor, Props}
import akka.event.Logging

import scala.concurrent.ExecutionContext

/** * Created by ctao on 15-12-16. */
object ExecutionContextTest extends App{

  /** * 执行对象 * @param runnable runnable * @param tag 标签 */
  case class Executor(runnable: Runnable,tag:String)

  /** * 停止指令 */
  case object ShutDown

  class ExecutionContextActor extends Actor{
    val logger = Logging(context.system,this)
    val exec = ExecutionContext.global
    override def receive: Receive = {
      case Executor(runnable,tag) =>
        logger.info(s"prepare execute $tag")
        exec.execute(runnable)
        logger.info(s"finished execute $tag")
      case ShutDown => logger.info("shutdown")
        context.system.terminate()
    }
  }


  val execute = system.actorOf(Props[ExecutionContextActor])

  for(i <- 1 to 10) execute ! Executor(getPrintRunnable(i),s"tag num: $i")
  Thread sleep 1000
  execute ! ShutDown

  /** * * @param i i标签 * @return 一个Runnable对象,其实这里也可以用工厂做,或者用伴生对象做 */
  def getPrintRunnable(i:Int) = new Runnable {
    override def run(): Unit = println(s"execute println $i")
  }
}

scala并发编程第八章4-7题_第1张图片

5

实现FailureDetector类,每隔interval变量设置的时间就向指定的actor对象发送Indentify消息,如果该actor无法在threshold规定的时间内回复ActorIdentity消息,则应该向其父actor发送failed消息

package com.linewell.chapter8

import akka.actor._
import akka.event.Logging
import akka.pattern._
import akka.util.Timeout
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._

/** * Created by ctao on 15-12-17. */
object FailureDetectorTest extends App {

  case class Failed(path: String)

  case class Check(actorPath: String, interval: Long, threshold: Long)

  case class Create(name: String)

  class ChildActor extends Actor {
    val logger = Logging(context.system, this)

    override def receive: Receive = {
      case str: String => logger.info("str")
      case Identify(y) => Thread sleep 1000
        sender() ! ActorIdentity(self.path.toString, Some(self))
    }

    override def unhandled(msg: Any) = {
      logger.info(s"cannot handle message $msg in this state.")
    }
  }

  class ParentActor extends Actor {
    val logger = Logging(context.system, this)

    override def receive: Actor.Receive = {
      case Create(name) => context.actorOf(Props[ChildActor], name)
      case Failed(x) => logger.info(s"child $x is die")

    }
  }

  class FailureDetectorActor extends Actor {
    override def receive: Actor.Receive = {
      case Check(actorPath, interval, threshold) => while (true) {
        implicit val timeout = Timeout(threshold.nanosecond)
        pipe(context.actorSelection(actorPath) ? Identify(actorPath)) to sender()
        Thread sleep interval
      }
    }
  }

  class Master extends Actor {
    val failureDetectorActor = system.actorOf(Props[FailureDetectorActor], "failure")
    val logger = Logging(context.system, this)

    override def receive: Actor.Receive = {
      case Check(actorRef, interval, threshold) => failureDetectorActor ! Check(actorRef, interval, threshold)
      case ActorIdentity(path, Some(ref)) => logger.info(s"$ref is live ")
      case ActorIdentity(path, None) => context.actorSelection(s"${findParent(path.toString)}") ! Failed(path.toString)
    }
  }

  val master = system.actorOf(Props[Master], "master")
  val parent = system.actorOf(Props[ParentActor], "parent")
  parent ! Create("child1")
  master ! Check("/user/parent/child1", 1000, 1)


  def findParent(path:String) = path.substring(0,path.lastIndexOf("/"))

}

scala并发编程第八章4-7题_第2张图片
scala并发编程第八章4-7题_第3张图片

6

分布式hash是一种分布在多台计算机上的集合,一台计算机拥有该集合的部分数据称为分片,请用DistributedMap实现:

package com.linewell.chapter8

import akka.actor.{Actor, ActorRef, Props}
import akka.event.Logging
import akka.pattern._
import akka.util.Timeout

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.util.{Failure, Success}

/** * Created by ctao on 15-12-18. */
object DistributedMapTest extends App {

  case class Get[K <: Any](key: K)

  case class SetValue[K <: Any, V <: Any](key: K, value: V)

  class DistributeMap[K <: Any, V <: Any](shards: ActorRef*) {

    implicit val timeout = Timeout(10.seconds)

    def hash(k: K) = k.hashCode() % shards.size


    def update(key: K, value: V): Future[Unit] = {
      val f = shards(hash(key)) ? SetValue(key, value)
      f.asInstanceOf[Future[Unit]]
    }

    def get(key: K): Future[Option[V]] = {
      val f = shards(hash(key)) ? Get(key)
      f.asInstanceOf[Future[Option[V]]]
    }
  }


  class ShardActor[K <: Any, V <: Any] extends Actor {
    val map = collection.mutable.Map[Any, Any]()
    val logger = Logging(context.system, this)

    override def receive: Receive = {
      case SetValue(key, value) =>
        logger.info(s"insert into map key $key,value $value path ${self.path}")
        map += (key -> value)

      case Get(key) =>
        logger.info(s"get $key ,path ${self.path}")
        sender() ! map.get(key)

    }
  }

  val a = system.actorOf(Props[ShardActor[Int, String]], "a")
  val b = system.actorOf(Props[ShardActor[Int, String]], "b")
  val c = system.actorOf(Props[ShardActor[Int, String]], "c")
  val dis = new DistributeMap[Int, String](a, b, c)
  for (i <- 1 to 10) yield dis.update(i, i.toString)

  val f = for (i <- 1 to 10) yield dis.get(i)
  f.foreach(x => x.onComplete {
    case Success(y) => println(s"get value ${y.get}")
    case Failure(e) => println(e.getMessage)
  })

  Thread sleep 1000
  system.terminate()
}

scala并发编程第八章4-7题_第4张图片

你可能感兴趣的:(编程,scala,并发)