2009-10-29 22 views
10

जावा में, कोई एक बहु-थ्रेडेड वातावरण में आवश्यक संसाधनों तक पहुंचने वाले विधियों या ब्लॉक को सिंक्रनाइज़ करेगा।स्कैला कलाकारों में साझा संसाधन तक पहुंचने का उचित तरीका

मैं सोच रहा हूं कि ऐसा करने का "स्कैला अभिनेता" तरीका कैसे काम करेगा।

मान लीजिए कि मेरे पास java.sql.Connection ऑब्जेक्ट्स का कनेक्शन पूल है जो मैं थ्रेड-सुरक्षित पहुंच प्रदान करना चाहता हूं। मैं इसे एक अभिनेता के रूप में कार्यान्वित करता हूं जो संदेश प्राप्त करता है और प्रेषक को एक कनेक्शन वापस भेजता है।

यह वहाँ तीन तरीके यह करने के लिए लगता है:

  1. उपयोग एक भविष्य
  2. उपयोग !?
  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) 
    } 
} 

भविष्य का संस्करण साफ दिखता है, इस तथ्य को छोड़कर कि मैं हमेशा के लिए ब्लॉक कर सकता हूं।

कोई विचार, या इस गलत की मेरी पूरी धारणा है?

उत्तर

2

यह खराब शैली हो सकती है लेकिन एक तरीका है कि आपके अभिनेता (जिसके लिए कनेक्शन की आवश्यकता है) को कनेक्शन पूल को सीधे प्लग करने के लिए अनिवार्य और कार्यात्मक शैलियों को मिलाकर Connection प्राप्त करने के लिए सिंक्रनाइज़ेशन का उपयोग करें। ईमानदार होने के लिए, मैं वास्तव में नहीं देखता कि इस दृष्टिकोण में क्या गलत है; मैं इसे !! या !? पर पसंद करता हूं, जो सिर्फ डेडलॉक (या यहां तक ​​कि livelock) चिल्लाता है!

मुझे लगता है कि एक अन्य तरीका है अपने पूल जो काम जो कनेक्शन और परिणाम के लिए एक संभावित लक्ष्य के साथ किया जा करने की जरूरत व्यक्त करने के लिए एक संदेश भेजने के लिए होगा:

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

और फिर आप उपयोग कर सकते हैं यह इस प्रकार:

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

या:

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

मैं वास्तव में एक कनेक्टेड पूल का उपयोग कर कलाकारों और साझा संसाधनों तक पहुंचने के साधनों के बारे में पूछने के साधन के रूप में उपयोग कर रहा हूं। क्या आप कह रहे हैं कि साझा संसाधनों को साझा संसाधन तक पहुंचने के लिए उपयोग नहीं किया जाना चाहिए? – davetron5000

+0

नहीं - मैं यह बिल्कुल नहीं कह रहा हूं। हालांकि, एक ही कनेक्शन पूल के साथ कई कलाकारों को इंजेक्शन दिया जा सकता है और कनेक्शन प्राप्त करने के लिए उपयुक्त 'सिंक्रनाइज़ेशन' का उपयोग किया जा सकता है। आपके द्वारा वर्णित अन्य विधियों में से कोई भी मान्य है, लेकिन मैं निश्चित रूप से अभिनेताओं पर किसी भी अवरुद्ध कॉल से बचूंगा। –

+0

मुझे लगता है कि मेरा प्रश्न "थ्रेड और सिंक्रनाइज़ेशन कठिन/कठिन/महान नहीं है और यही कारण है कि स्कैला अभिनेता" स्कूल लागू करता है। यानी, मुझे बताया गया है कि स्कैला अभिनेताओं के साथ मिलनसार हल करती है। तो, इस बहुत ही साधारण मामले में, पैटर्न क्या है? तीसरा संस्करण एकमात्र ऐसा है जो अवरुद्ध करने से बचाता है, लेकिन ऐसा लगता है कि मुझे – davetron5000

0

करने का अभिनेता जिस तरह से यह नहीं है संसाधन साझा नहीं कर रहा हूँ। सभी को एक ऐसे अभिनेता को खिलाया गया है जिसका काम साझा संसाधन तक पहुंच से निपटना है।

इस तरह, संसाधन स्वयं धागे के बीच साझा नहीं किया जाता है। अभिनेता है।

+0

इसके साथ समस्या यह है कि यदि आपके पास एक 'दृढ़ता' अभिनेता है, तो आपने एक बाधा उत्पन्न की है । लेकिन अगर आप 'कनेक्शन प्रदाता' अभिनेता चाहते हैं और कॉल अवरुद्ध करने से बचाना चाहते हैं, तो कोई * अच्छा * समाधान –

+0

सही नहीं है, कनेक्शन स्वयं संसाधन साझा नहीं होते हैं; कनेक्शन का पूल है; यही कारण है कि मैं संसाधनों के पूल के मालिक के लिए एक अभिनेता का उपयोग कर रहा हूं। मैं सोच रहा हूं कि अभिनेता मॉडल पूल से संसाधनों तक पहुंचने के लिए डब्लूआरटी कैसे काम करता है। – davetron5000

संबंधित मुद्दे