scala同時プログラミング第二章練習問題


1
計算操作を実行する2つのコードブロックaおよびbを受信し、計算結果を含むメタグループを返し、署名するparallelという方法を実装する.
def parallel[A,B](a: => A,b: =>B):(A,B)

インプリメンテーション
object Test1 extends App {
  def parallel[A, B](a: => A, b: => B): (A, B) = {
    var x = null.asInstanceOf[A]
    var y = null.asInstanceOf[B]
    new Thread{
      override def run(): Unit ={
        x = a
      }
    }.start()

    new Thread{
      override  def run(): Unit ={
        y = b
      }
    }.start()
    (x,y)
  }
}

2
時間を測定するためのパラメータdurationと計算操作を実行するコードブロックを受信すべきperiodicallyという方法を実装し、パラメータdurationが設定された期間が経過するたびに、コードブロックbを実行するスレッドを実行し、
def periodically(duraction:Long)(b: =>Unit):Unit

インプリメンテーション
/**
  * Created by ctao on 2015/11/30.
  */
object Worker extends  App{
  def periodically(duration: Long)(b: => Unit): Unit = {
    def work() = {
      new Thread {
        override def run(): Unit = {
          b
          Thread sleep duration
        }
      }.start()
    }

    while (true) {
      work()
    }
  }

  periodically(1000)(println("Hello"))
}

3
次のインタフェースを使用してSyncVarというクラスを実装します.
class SyncVar[T]{
    def get():T = ???
    def put(x:T):Unit = ???
}

SyncVarの作成が完了したらNull値にし、getを呼び出して例外を投げ出し、putを呼び出して値を追加し、値を設定した後にgetが値を得、putが例外を投げ出す
/**
  * Created by ctao on 2015/11/30.
  */
class SyncVar[T] {
  private var empty = false
  private var value :T = null.asInstanceOf[T]
  def get():T = this.synchronized{
    if(empty){
      throw new Exception("empty")
    }else{
      empty = false
      value
    }
  }

  def put(x:T):Unit = this.synchronized{
    if(empty){
      empty = false
      value = x
    }else{
      throw  new Exception("not empty")
    }
  }
}


4
前のオブジェクトを再実装し、オブジェクトでisEmptyとnonEmptyメソッドを実装し、さらに1つのメーカーと消費者を実装し、0-15デジタル伝達消費を行う
/**
  * Created by ctao on 2015/11/30.
  */
class SyncVar2[T] {
  private var empty = true
  private var value:T = null.asInstanceOf[T]
  def get():T = {
    if(empty){
      throw  new Exception("empty")
    }else{
      empty = true
      value
    }
  }
  def isEmpty = this.synchronized(empty)
  def nonEmpty = this.synchronized(!empty)
  def put(x:T) = this.synchronized{
    if(empty){
      empty = false
      value = x
    }else{
      throw  new Exception("nonempty")
    }
  }

}

object  TestSyncVar2 extends  App{
  val syncVar = new SyncVar2[Int]
  new Thread{
    override def run(): Unit ={
      var x = 0
      while(x <15){
        if(syncVar.isEmpty){
          syncVar.put(x)
          x += 1
        }
      }
    }
  }.start()


  new Thread{
    override  def run(): Unit ={
      var x = 0
      while(x != 15){
        if(syncVar.nonEmpty){
          println(syncVar.get())
          x += 1
        }
      }
    }
  }.start()
}

5
2つの方法を実装
def getWait():T
def putWait(x:T):Unit

残りは上記のようなもので、待機を実現するだけです.
/**
  * Created by ctao on 2015/11/30.
  */
class SyncVar3[T] {
  private var empty = true
  private var value:T = null.asInstanceOf[T]

  def isEmpty = this.synchronized(empty)
  def nonEmpty = this.synchronized(!empty)
  def getWait:T = this.synchronized{
    while(empty){
      this.wait()
    }
    empty = true
    value
  }
  def putWait(x:T):Unit = this.synchronized{
    while (!empty){
      this.wait()
    }
    empty = false
    value = x
    this.notify()
  }
}


object  TestSyncVar3 extends  App{
  val syncVar = new SyncVar3[Int]
  new Thread{
    override def run(): Unit ={
      var x = 0
      while(x <15){
        if(syncVar.isEmpty){
          syncVar.putWait(x)
          x += 1
        }
      }
    }
  }.start()


  new Thread{
    override  def run(): Unit ={
      var x = 0
      while(x != 15){
        if(syncVar.nonEmpty){
          println(syncVar.getWait)
          x += 1
        }
      }
    }
  }.start()
}

6
複数値を格納するキューの実装
/**
  * Created by ctao on 2015/11/30.
  */
class SyncQueue[T](val num:Int) {
  private val syncQueue = collection.mutable.Queue[T]()

  def getWait:T = this.synchronized {
    while (syncQueue.isEmpty) {
      this.wait()
    }
    val value = syncQueue.dequeue()
    this.notify()
    value
  }


  def putWait(x:T) = this.synchronized{
    while(syncQueue.length == num){
      this.wait()
    }
    syncQueue.enqueue(x)
    this.notify()
  }

}

object TestSyncQueue extends App{
  val queue = new SyncQueue[Int](5)
  new Thread{
   override  def run(): Unit ={
     var x= 0
     while(x<11){
       queue.putWait(x)
       x+=1
     }
   }
  }.start()


  new Thread{
    override  def run(): Unit ={
      var x = 0
      while(x<10){
        x = queue.getWait
        println(x)
      }
    }
  }.start()
}

7
一括振替の実現
def sendAll(accounts:Set[Accout],target:Account):Unit

インプリメンテーション

/**
  * Created by ctao on 2015/11/30.
  */
class Account(val name:String,var money:Int)

object  AccountTest extends  App{
  def sendAll(accounts:Set[Account],target:Account):Unit = {
    for(accountdef send(a:Account,b:Account,num:Int): Unit = this.synchronized{
    println(s"${a.name} send $num to ${b.name} ,${a.money},${b.money}")
    a.money -= num
    b.money += num
    println(a.money,b.money)
  }


  val a = new Account("a",10000)
  val b = new Account("b",20000)
  val c = new Account("c",30000)
  val d = new Account("d",40000)
  val e = new Account("e",50000)
  val f = new Account("f",60000)
  val g = new Account("g",0)


  val sets = Set[Account](a,b,c,d,e,f)

  sendAll(sets,g)



}

8-9前の記事で言及したが、ここでは省略する.
scalaプロファイリングPriorityQueue,重み値の使用