写入BufferedWriter的最佳Scala线程安全方法是什么?

Chi*_*per 4 multithreading scala bufferedwriter playframework playframework-2.4

我有一个简单的方法,将一行数据写入一个文件后跟一个异步执行的新行.

  def writeToFile(bw: BufferedWriter, str: String) = {
    bw.write(str)
    bw.newLine
  }
Run Code Online (Sandbox Code Playgroud)

当我的程序运行时,由于调用的异步性质,我在文件中得到"混合"行.例如...说writeToFile(bw,"foo")异步执行3次我可能得到:

正确的输出

FOO

FOO

FOO

可能输错

foofoo

FOO

我可以通过使用这样的synchronized方法来避免这种可能性:

  def writeToFile(bw: BufferedWriter, str: String) = synchronized {
    bw.write(str)
    bw.newLine
  }
Run Code Online (Sandbox Code Playgroud)

根据我的研究,我无法确定这对于扩展我的应用程序是多么"安全".我可以使用synchronized查找的唯一示例是访问集合时,而不是写入文件.我的应用程序是在Play中构建的!框架2.4.2.

Yur*_*hov 8

我个人会为每个BufferedWriter创建一个akka actor,它将完全封装它.

import java.io.BufferedWriter
import akka.actor._
import playground.BufferedWriterActor.WriteToBuffer

object BufferedWriterActor {
  val name = "BufferedWriterActor"
  def props(bw: BufferedWriter) = Props(classOf[BufferedWriterActor], bw)

  case class WriteToBuffer(str: String)
}

class BufferedWriterActor(bw: BufferedWriter) extends Actor {

  def receive: Actor.Receive = {
    case WriteToBuffer(str) =>
      bw.write(str)
      bw.newLine()
  }
}
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

import akka.actor.{ActorSystem, Props}

object HelloWorld {
  def main(args: Array[String]): Unit = {
    val system = ActorSystem("mySystem")

    // Share this actor across all your threads.
    val myActor = system.actorOf(BufferedWriterActor.props(bw), BufferedWriterActor.name)

    // Send messages to this actor from all you threads.
    myActor ! BufferedWriterActor.WriteToBuffer("The Text")
  }
}
Run Code Online (Sandbox Code Playgroud)

这将在单个线程中链接对此缓冲区的所有调用.

关于akka及其演员的更多信息在这里:

http://akka.io/

http://doc.akka.io/docs/akka/snapshot/scala/actors.html

播放框架本身也使用akka,所以你应该能够使用它的默认ActorSystem,但我不记得究竟是怎么回事.