2010-11-11 11 views
7

थ्रेड के बजाए अभिनेताओं के संदर्भ में कैसे सोचें, इस पर एक संभाल पाने की कोशिश कर रहा है। मैं निम्नलिखित उपयोग मामले पर थोड़ा सा स्टंप हूं:थ्रेड मॉडल से अभिनेताओं तक संक्रमण

ऐसी प्रणाली पर विचार करें जिसमें एक निर्माता प्रक्रिया है जो काम करता है (उदाहरण के लिए फ़ाइल से डेटा पढ़कर), और कई कार्यकर्ता प्रक्रियाएं जो काम का उपभोग करती हैं (उदाहरण के लिए डेटा को पार्स करके और इसे डेटाबेस में लिखकर)। जिस दर पर काम किया जाता है और उपभोग किया जाता है, वह भिन्न हो सकता है, और सिस्टम को इसके लिए मजबूत रहना चाहिए। उदाहरण के लिए, यदि मजदूर नहीं रह सकते हैं, तो निर्माता को इसका पता लगाना चाहिए और अंत में धीमा या इंतजार करना चाहिए।

इस धागे के साथ लागू करने के लिए बहुत आसान है:

val producer:Iterator[Work] = createProducer() 
val queue = new LinkedBlockingQueue[Work](QUEUE_SIZE) 
val workers = (0 until NUM_WORKERS) map { i => 
    new Thread() { 
    override def run() = { 
     while (true) { 
     try { 
      // take next unit of work, waiting if necessary 
      val work = queue.take() 
      process(work) 
     } 
     catch { 
      case e:InterruptedException => return 
     } 
     } 
    } 
    } 
} 

// start the workers 
workers.foreach(_.start()) 

while (producer.hasNext) { 
    val work = producer.next() 
    // add new unit of work, waiting if necessary 
    queue.put(work) 
} 

while (!queue.isEmpty) { 
    // wait until queue is drained 
    queue.wait() 
} 

// stop the workers 
workers.foreach(_.interrupt()) 

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

उत्तर

3

क्योंकि अभिनेता संदेश "ऑफ़लाइन" संसाधित करते हैं (यानी संदेश की खपत उनके प्राप्त होने के लिए असंबंधित है), यह देखना मुश्किल है कि "निर्माता उपभोक्ताओं को पकड़ने के लिए इंतजार कर रहा है" का सटीक एनालॉग कैसे हो सकता है।

case object MoreWorkPlease 
class Consumer(prod : Producer) extends Actor { 
    def act = { 
    prod ! MoreWorkPlease 
    loop { 
     react { 
     case Work(payload) => doStuff(payload); reply(MoreWorkPlease) 
     } 
    } 
    } 
} 

class Producer extends Actor { 
    def act = loop { 
    react { 
     case MoreWorkPlease => reply(Work(getNextItem)) 
    } 
    } 
} 

यह न सही, ज़ाहिर है, क्योंकि निर्माता नहीं है "पढ़ा जाता है:

केवल एक चीज मैं के बारे में सोच सकते हैं उपभोक्ताओं निर्माता अभिनेता से काम (जो reply उपयोग करता है) अनुरोध है कि है आगे "और केवल उपभोक्ता इसके लिए तैयार होने पर ही काम करता है। उपयोग कुछ ऐसा होगा:

val prod = new Producer 
(1 to NUM_ACTORS).map(new Consumer(prod)).foreach(_.start()) 
prod.start() 
+0

एचआरएम, यह एक समाधान है जिसे मैंने सोचा था। यह शायद पर्याप्त है, लेकिन इसके साथ मेरी चिंता यह है कि यदि श्रमिक निर्माता को पीछे छोड़ देते हैं, तो एक कार्य बफर की कमी के परिणामस्वरूप खराब प्रदर्शन होता है। – toluju

+0

@toluju - प्रत्येक उपभोक्ता को काम के लिए पूछना शुरू करें, और निर्माता को इन संदेशों पर प्रतिक्रिया दें, लेकिन उन्हें प्राप्त करें, और यदि उन्हें अभी तक और अधिक काम नहीं किया गया है तो उन्हें एक कतार में रखें। (फिर, एक बार काम होने के बाद, यह कतार में वस्तुओं को विभाजित कर सकता है।) –