Java では、マルチスレッド環境で必要な共有リソースにアクセスするメソッドまたはブロックを同期します。
これを行う「Scala Actors」の方法がどのように機能するのか疑問に思っています。
java.sql.Connectionスレッドセーフなアクセスを提供したいオブジェクトの接続プールがあるとします。メッセージを受信し、送信者に接続を返すアクターとして実装します。
これを行うには、次の 3 つの方法があるようです。
- 未来を使う
- 使用する
!? - 必要なクラスを
Connectionアクターにする
コード:
sealed abstract class ConnectionPoolMessage
case class NewConnection extends ConnectionPoolMessage
case class CloseConnection(c:Connection) extends ConnectionPoolMessage
class ConnectionPool extends Actor {
def act() {
while (true) {
receive() {
case NewConnection => sender ! getConnectionFromPool
case CloseConnection(conn) => returnConnection(conn)
}
}
}
}
// Here, my "do stuff" method is all in one place, and I block waiting
// on the Future from the pool; however this could take forever and cause trouble
class UsingFuture {
val pool = new ConnectionPool
def doSomething() {
val connectionFuture = pool !! NewConnection
val connection = connectionFuture() // concerned that we can't timeout here
// do stuff with my Connection instance
pool ! CloseConnection(connection)
}
}
// here, I wait and just use a timeout
// Seems clean to me, I guess.
class UsingBangQuestion {
val pool = new ConnectionPool
def doSomething() {
pool !?(TIMEOUT,NewConnection) match {
case Some(conn) => {
// do something with connection
pool ! CloseConnection(conn)
}
case None => throw new RuntimeException("timed out")
}
}
}
// here, I don't worry about timeouts, cause I only use the
// the connection when I receive a message back with it.
// The problem is that I now have to split my logic up
// with two methods
class AsAnActor extends Actor {
val pool = new ConnectionPool
def startSomething() {
start
pool ! NewConnection
}
def act() {
receive() {
case conn:Connection => finishSomething(conn)
}
}
def finishSomething(conn:Connection) {
// do stuff with my Connection
pool ! CloseConnection(conn)
}
}
永久にブロックできるという事実を除けば、Future バージョンが最もクリーンに見えます。
何か考えがありますか、それとも私の考え全体が間違っていますか?