0

私は最近、scala の並行実装をチェックするように言われた新米の Java コーダーです。単純な (同時実行性を説明するのには最適ではありませんが) 例として、アクターにエラトステネスのふるいを解かせることが考えられます。私はこれまで何かをまとめてきましたが、私が進んでいる方向が正しいかどうかさえよくわかりません. これが私の現在のコードです:

import scala.actors.Actor
import scala.actors.Actor._
import Array._

class PrimeActor(val id: Int) extends Actor {

     //Runs one Prime of the Sieve of Eratosthenes
     def sieve(p: Int, list: Array[Int]) {
       var i = 1
       var place = 0
       while(list contains (i * p)) {
       place = list.indexOf(i * p)
       if (list(place) != 0) 
          list.update(place, 0)
       i += 1
       }
     }

   //Checks to see if there is a higher prime in the list
   //If so, creates a new actor to handle it and sends
   //it the list and the prime
   def findandCreateNextPrime(p: Int, list: Array[Int]){
      var i = 1
      var place = list.indexOf(p)
      while(list(place + i) == 0 && (p + i) <= list.last) {
         i += 1
      }
      val newP = list(place+i)

      if (list contains (p + i)) {
         if ((p + i) equals list.last) {
            print(list.last)
         } else {
            print(", ")
            val pA = new PrimeActor(newP)
            pA.start()
            pA ! (list(newP), list)
         } 
     } else {
     println("DONE")
    } 
  }

   //Actor behavior
   def act() {
      loop {
         react{
            case (recievedP: Int, recievedList: Array[Int]) =>
               print(recievedP)
               sieve(recievedP, recievedList)
               findandCreateNextPrime(recievedP, recievedList)
               exit()
         }
      }
   }
}

任意のヘルプまたは指示入力をいただければ幸いです。ありがとう!

4

2 に答える 2

4

Scalaでは、コードを機能的なスタイルで書くことができます。使用することをお勧めします。まず忘れてくださいArray、それは可変コレクションであり、scalaの可変コレクションは邪悪です。不変のコレクションをとして使用することをお勧めしListます。同じことはについて言うことvarです。可能な限り使用してみてくださいval
Scalaでエラトステネスのふるいを実装する最も簡単な方法は次のとおりです。

import scala.annotations.tailrec

def sieve(until: Int): Seq[Int] = {
  @tailrec
  def loop(i: Int, primes: Seq[Int]): Seq[Int] = {
    // we reached the desired end
    if (i > until) primes
    else {
      // we already found a factor of this i
      if (primes exists(i % _ == 0)) loop(i + 2, primes)
      // we found a new prime
      else loop(i + 2, primes :+ i)
    }
  }
  // there is no prime smaller than 2
  if (until < 2) Seq.empty[Int]
  // starting with 3 has the advantage, we only need to check i + 2
  else loop(3, Seq.empty[Int] :+ 2)
}

Scalaを使い始めたばかりの場合、これは少し混乱するかもしれませんが、説明します。
特定の数までのすべての素数のシーケンスが必要です。素数であるかどうかを1秒おきにチェックする再帰関数を定義します。末尾再帰であるため、コンパイラーはそれを理解のために最適化します。したがって、StackOverflowsについて気にする必要はありません。カウンターが最大値(until)を超えると、素数が返され、検出されました。これが私たちの再帰アンカーです。それ以外の場合は、現在の要素である素数が見つかったかどうかを確認しますi。存在する場合は、次の候補にスキップします。それ以外の場合はi、素数を追加して次の候補に進みます。
注:アノテーションは必須ではありませんが、アノテーションが存在する場合、関数が末尾再帰でない場合、コンパイラーは警告を出します。

私が提案したコードを使用すると、問題が発生します。これ以上、同時実行を使用することはできません。Scalaでの同時実行の良い入門書は、ProgrammingScalaの章です。彼らは、居眠り床屋の問題を同時発生によって解決しました。ここに彼らの解決策へのリンクがあります。

于 2012-08-13T12:38:14.593 に答える
-1

アクターは並行性に関するものです。さまざまなタスクが同時に実行され、必要に応じて互いに通信します。

アクターについては、次の 2 つの非常に重要な点があります。

  1. 俳優とはメッセージでのみ会話します。アクターがリターンでメッセージを送り返していない場合、またはメッセージ以外の場所から情報を取得している場合、それは間違っています。
  2. 変更可能なデータ構造をアクターに送信しません。あなたがそれをするなら、あなたはそれを間違っています。

したがって、あなたの例では両方のルールに違反しており、アクター間の相互作用は実際にはありません。これらの理由から、ここではアクターの選択はおそらく間違っています。そのような場合、答えを得るために並列コレクションを調べた方がよいかもしれませんが、ここでも役に立ちません。

エラトステネスのふるいは本質的にシリアル アルゴリズムであり、並列処理または同時実行処理のいずれかを選択するのは不適切です。

于 2012-08-13T14:36:28.030 に答える