我怎样才能使这个可能简单的Producer actor示例工作?

时间:2011-03-31 18:46:14

标签: scala concurrency actor

我正在尝试编写一个简单的生成器类,以便学习Actors。我希望有一个生产者,它以某个目录开头,由File对象表示,然后将消息发送给其他actor以处理这些文件。最初,我正在阅读文件的内容,但是,为了简单起见,现在我只是收集它们的路径。 再一次,这没有真正的世界价值,但它对我有实际价值,因为我认为这将使我更好地理解演员。这是我到目前为止所做的:

import java.io._
import java.util.concurrent._
import scala.actors.Actor
import scala.io.Source
import java.util.concurrent.locks.ReentrantLock
import java.util.concurrent.atomic.AtomicLong

case class FileSystemObject(path:File)
case class FileContent(content:String)

case object Stop
case object Processed

class ResultAcumulator extends Actor {

    var results:List[String] = Nil
    var finished = false

    def act() = {
        loop {
            react {
                case FileContent(content) => {
                    results ::= content
                }
                case Stop => {
                    finished = true;
                    exit
                }
            }
        }
    }
}

class FileSystemReader(accumulator:Actor) extends Actor {
    def act() = {
        loop {
            react {
                case FileSystemObject(path) => {
                    if(path.isFile) {
                        accumulator ! FileContent(path.toString)
                        sender ! Processed
                    }
                }
                case Stop => exit
            }
        }
    }
}

class FileSystemProducer(start:File,acumulator:Actor,reader:Actor) extends Actor {
    var totalFilesProcessed = 0

    def act() = {
        val files = start.listFiles
        files.foreach{ f =>
            (reader ! FileSystemObject(f))
        }
        loop {
            react {
                case Processed => {
                    totalFilesProcessed += 1
                    if(totalFilesProcessed == files.length) {
                        reader ! Stop
                        acumulator ! Stop
                        Xo.decrementLatch
                    }
                }
            }
        }

    }
}
object Xo {

     var latch = new CountDownLatch(1)

     def decrementLatch = latch.countDown

     def main(args : Array[String]) = {

         val acumulator = new ResultAcumulator
         val fsReader = new FileSystemReader(acumulator)
         val producer = new FileSystemProducer(new File("d:/rails/a"),acumulator,fsReader)

         acumulator.start
         fsReader.start
         producer.start

         latch.await

         acumulator.results.foreach(println)

     }
}

现在处于状态,它会永远运行,我看不到输出。啊,还有一件事。在程序退出之前,我希望它列出“已处理”的结果。我搜索了一下,找到了CountDownLatch类。我想用循环/反应而不是while / receive来实现这个。我很确定问题是由于我有以下这些问题引起的:

files.foreach{ f =>
    (reader ! FileSystemObject(f))
}

并且我的反应循环稍低,但我不知道如何修复它。

1 个答案:

答案 0 :(得分:3)

我猜相关部分是                 case FileSystemObject(path)=> {                     if(path.isFile){                         累加器! FileContent(path.toString)                         发件人!处理                     }                 } 这里不是“普通文件”的东西,例如目录,不会被发送到累加器。 因此,如果“d:/ rails / a”中存在子目录,则测试totalFilesProcessed == files.length将始终失败。