繁体   English   中英

斯卡拉演员总理筛

[英]Scala Actor Prime Sieve

我是一个新来的Java编码器,最近被告知要检查scala的并发实现。 我认为一个简单的(虽然不是最好的并发例子)示例可能是让演员解决Eratosthenes的筛网。 到目前为止,我已经整理了一些东西,但是我不确定我要走的方向是否正确。 这是我当前的代码:

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()
         }
      }
   }
}

任何帮助或定向输入将不胜感激。 谢谢!

在Scala中,您可以以功能样式编写代码。 我建议您使用它。 首先,忘记Array ,它是一个可变集合,scala中的可变集合是邪恶的。 最好将不可变集合用作List var 尽可能尝试使用val
我猜,在Scala中实现Eratosthenes筛子的最简单方法是:

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,这可能会有点混乱,但是我会解释。
我们想要一个所有素数的序列,直到一个特定的数。 我们定义了一个递归函数,它将检查第二个数字是否为质数。 因为它是尾递归的,所以编译器会将其优化为可理解的,因此我们无需为StackOverflow烦恼。 如果我们的计数器超过最大值( until ),我们将检测到素数。 这是我们的递归锚。 否则,我们检查是否找到质数,这是我们当前的因素i 如果有一个,我们就跳到下一个候选者,否则我们将i加到素数上,然后继续下一个候选者。
注意:注释不是必需的,但如果函数不尾递归,则注释(如果存在)会在编译器警告您。

使用我建议的代码会导致问题,您不能再使用并发性。 编程Scala中的一章很好地介绍了Scala中的并发性 他们通过并发解决了熟睡中的理发师问题。 这是他们解决方案的链接

参与者与并发有关:并发完成不同的任务,并根据需要相互通信。

关于演员,有两个非常重要的事情:

  1. 您只能通过消息与演员交谈。 如果您的演员没有将返回的消息发送回去,或者从消息以外的其他地方获取信息,则说明您做错了。
  2. 您不会将可变数据结构发送给参与者。 如果这样做,则说明您做错了。

因此,您在示例中违反了这两个规则,并且参与者之间实际上没有任何交互。 由于这些原因,演员在这里可能是错误的选择。 在这种情况下,最好查看并行集合的答案,但它们在这里也无济于事。

Eratosthenes的筛子是一种固有的串行算法,对于并行性或并发性来说都是一个错误的选择。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM