2009-10-29 18 views
10

Java'da, biri çok iş parçacıklı bir ortamda gereken paylaşılan bir kaynağa erişen yöntemleri veya blokları eşitlerdi.Scala aktörlerinde paylaşılan kaynağa erişmek için uygun yol

Bunu yapmak için "Scala Aktörleri" nin nasıl çalışacağını merak ediyorum.

İplik güvenli erişim sağlamak istediğim bir java.sql.Connection nesnesi bağlantı havuzum var. İletileri alan ve göndericiye geri bağlantı gönderen bir oyuncu olarak uygularım.

Bunu yapmak için üç yol var gibi görünüyor:

:

  1. Kullanım !?
  2. Connection aynı zamanda bir aktör

Kod olmak gerek sınıfını var bir Gelecek

  • Kullanım
    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) 
        } 
    } 
    

    Gelecek versiyonu, sonsuza dek engelleyebileceğim dışında temiz görünüyor.

    Düşünceleriniz ya da benim bu yanlış düşüncem nedir?

  • cevap

    2

    Kötü bir stil olabilir, ancak bir yol, bağlantınızın doğrudan bağlantıya sahip olmasını ve eşitleme özelliğini Connection almak için aktörünüzün (bağlantı gerektiren) aktörünüze alarak, zorunlu ve işlevsel stilleri karıştırmaktır. Dürüst olmak gerekirse, bu yaklaşımda neyin yanlış olduğunu göremiyorum; Ben sadece kilitlenme (veya livelock) çığlık atan !! veya !? bir tane tercih ederim!

    class DbWork(f: Connection => Unit) 
    class DbWorkWithResult[T](f:Connection => T, target: OutputChannel[Any]) 
    

    Ve sonra kullanabilirsiniz:

    Bir başka yolu sonucu için bağlantı ve olası bir hedefle yapılması gereken işi dile sizin havuzuna bir mesaj göndermek için olacağını tahmin böylece:

    pool ! new DbWork({ (conn: Connection) => //do something 
           }) 
    

    Veya:

    pool ! new DbWorkWithResult[Int]((conn: Connection) => //return int 
           }, self) 
    
    +0

    Aslında bir bağlantı havuzunu aktörler ve paylaşılan bir kaynağa erişme araçları hakkında soru sormak için kullanıyorum. Paylaşılan bir kaynağa erişmek için aktörlerin kullanılmaması gerektiğini mi söylüyorsunuz? – davetron5000

    +0

    Hayır - Bunu hiç söylemiyorum. Ancak, aynı bağlantı havuzuna birden fazla oyuncu enjekte edilebilir ve bağlantı kurmak için uygun olduğunda 'senkronizasyon 'özelliğini kullanabilir. Açıkladığınız diğer yöntemlerden herhangi biri de geçerlidir, ancak aktörlere yapılan çağrıları engellemekten kesinlikle kaçınacağım. –

    +0

    Sanırım sorum şu: "Konular ve senkronizasyonlar zor/zor/harika değil ve Scala neden Aktörler kullanıyor" okulu. Yani, Scala'nın Aktörlerle eşzamanlılık kurduğu söylendi. Yani, bu çok basit durumda, desen nedir? Üçüncü sürüm, engellemeyi engelleyen tek şeydir, ama bana – davetron5000

    0

    yapmanın Aktörler yolu hayır mı t kaynakları paylaşma. Tüm erişim, paylaşılan kaynağa erişim ile uğraşmak olan tek bir Oyuncuya beslenir.

    Bu şekilde, kaynağın kendisi iş parçacıkları arasında paylaşılmaz. Aktördür.

    +0

    Buradaki sorun, tek bir “Persistence” oyuncunuz varsa, bir darboğaz getirmiş olmanızdır. . Ancak bir 'ConnectionProvider' oyuncusu istiyor ve aramaları engellemekten kaçınmak istiyorsanız, * güzel * çözüm yok. –

    +0

    Doğru, Bağlantıların kendileri paylaşımlı kaynaklar değildir; bağlantı havuzu; Bu yüzden kaynak havuzuna sahip olmak için bir Aktör kullanıyorum. Aktör modelinin WRT'yi havuzdan kaynaklara erişme konusunda nasıl çalıştığını merak ediyorum. – davetron5000

    İlgili konular