मल्टीथ्रेडिंग डिजाइन बेस्ट प्रैक्टिस

इस समस्या पर विचार करें: मेरे पास एक प्रोग्राम है जो डेटाबेस से 100 रिकॉर्ड्स लेना चाहिए (और कहें) प्रत्येक के लिए इसे वेब सेवा से अद्यतन जानकारी प्राप्त करनी चाहिए। इस परिदृश्य में समांतरता को पेश करने के दो तरीके हैं:

  1. मैं एक नए थ्रेड पर वेब सेवा के लिए प्रत्येक अनुरोध शुरू करता हूं। एक साथ थ्रेड की संख्या कुछ बाहरी पैरामीटर (या किसी भी तरह गतिशील रूप से समायोजित) द्वारा नियंत्रित होती है।

  2. मैं छोटे बैच बनाते हैं (चलो प्रत्येक के 10 रिकॉर्ड के बारे में कहते हैं) और प्रत्येक बैच को एक अलग धागे पर लॉन्च करें (इसलिए हमारा उदाहरण, 10 धागे लेना)।

कौन सा बेहतर दृष्टिकोण है, और आप ऐसा क्यों सोचते हैं?

0
ro fr bn
@ पैट्रिक वैसे, मैं गतिशील नियंत्रण के मामले में थ्रेडपूल के बारे में सोच रहा था। लेकिन मुझे लगता है कि मैं यह पता लगाने की कोशिश कर रहा हूं कि क्या दो दृष्टिकोणों के बीच कोई प्रदर्शन अलग है (वास्तव में थ्रेडपूल का उपयोग किया जा सकता है)। और यदि प्रदर्शन नहीं है, तो क्या कोई सर्वोत्तम अभ्यास करना चाहिए।
जोड़ा लेखक Vaibhav, स्रोत
यह एक ThreadPool के लिए नौकरी की तरह लगता है। बस नौकरियों को कतारबद्ध करें, और बाकी को संभाल लें।
जोड़ा लेखक Patrick, स्रोत
गतिशील/विन्यास योग्य, चूंकि इष्टतम संख्या पर्यावरण पर निर्भर करती है और वास्तव में बाधा क्या होती है।
जोड़ा लेखक Stu, स्रोत

4 उत्तर

विकल्प 3 सबसे अच्छा है:

Async IO का उपयोग करें।

जब तक आपका अनुरोध प्रसंस्करण जटिल और भारी न हो, आपका प्रोग्राम HTTP अनुरोधों के लिए 99% समय व्यतीत करने जा रहा है।

यह वही है जो Async IO के लिए डिज़ाइन किया गया है - विंडोज नेटवर्किंग स्टैक (या .नेट फ्रेमवर्क या जो कुछ भी) सभी प्रतीक्षाों के बारे में चिंता करें, और केवल एक थ्रेड का उपयोग प्रेषण के लिए करें और परिणामों को 'उठाएं'।

दुर्भाग्य से .NET ढांचा इसे गधे में सही दर्द बनाता है। यदि आप कच्चे सॉकेट या Win32 एपीआई का उपयोग कर रहे हैं तो यह आसान है। यहां एक (परीक्षण किया गया) उदाहरण है, वैसे भी सी # 3 का उपयोग कर:

using System.Net;//need this somewhere

// need to declare an class so we can cast our state object back out
class RequestState {
    public WebRequest Request { get; set; }
}

static void Main( string[] args ) {
   //stupid cast neccessary to create the request
    HttpWebRequest request = WebRequest.Create( "http://www.stackoverflow.com" ) as HttpWebRequest;

    request.BeginGetResponse(
        /* callback to be invoked when finished */
        (asyncResult) => { 
           //fetch the request object out of the AsyncState
            var state = (RequestState)asyncResult.AsyncState; 
            var webResponse = state.Request.EndGetResponse( asyncResult ) as HttpWebResponse;

           //there we go;
            Debug.Assert( webResponse.StatusCode == HttpStatusCode.OK ); 

            Console.WriteLine( "Got Response from server:" + webResponse.Server );
        },
        /* pass the request through to our callback */
        new RequestState { Request = request }  
    );

   //blah
    Console.WriteLine( "Waiting for response. Press a key to quit" );
    Console.ReadKey();
}

संपादित करें:

.NET के मामले में, 'समापन कॉलबैक' वास्तव में थ्रेडपूल थ्रेड में निकाल दिया जाता है, न कि आपके मुख्य थ्रेड में, इसलिए आपको अभी भी किसी भी साझा संसाधन को लॉक करने की आवश्यकता होगी, लेकिन यह आपको अभी भी थ्रेड प्रबंधित करने की सभी परेशानी बचाता है।

0
जोड़ा
क्या आपको वास्तव में राज्य वस्तु का उपयोग करके अनुरोध पारित करने की आवश्यकता है या क्या आप अनुरोध को बंद करने वाले चर के रूप में उपयोग कर सकते हैं?
जोड़ा लेखक zvikara, स्रोत

समानांतर Fx प्राप्त करें। ब्लॉकिंग कोलेक्शन देखें। रिकॉर्ड के बैचों को खिलाने के लिए एक थ्रेड का उपयोग करें, और सेवा में संग्रह से रिकॉर्ड खींचने के लिए 1 से n धागे। आप उस दर को नियंत्रित कर सकते हैं जिस पर संग्रह खिलाया जाता है, और वेब सेवाओं को कॉल करने वाले धागे की संख्या। इसे कॉन्फ़िगरेशन के माध्यम से कॉन्फ़िगर करने योग्य बनाएं, और संग्रह कार्य प्रतिनिधियों को खिलाकर इसे सामान्य बनाएं, और आपके पास एक अच्छा छोटा बैचर होगा जो आप अपने दिल की सामग्री का पुन: उपयोग कर सकते हैं।

0
जोड़ा

प्रोग्राम चलाने वाला कंप्यूटर शायद बाधा नहीं है, इसलिए: याद रखें कि HTTP प्रोटोकॉल में एक जीवित हेडर है, जो आपको एक ही सॉकेट पर कई GET अनुरोध भेजने देता है, जो आपको टीसीपी/आईपी हैंड शेक से बचाता है। दुर्भाग्यवश मुझे नहीं पता कि नेट पुस्तकालयों में इसका उपयोग कैसे किया जाए। (संभव होना चाहिए।)

आपके अनुरोधों का उत्तर देने में शायद देरी होगी। आप यह सुनिश्चित करने का प्रयास कर सकते हैं कि आपके पास हमेशा सर्वर पर बकाया अनुरोधों की एक निश्चित संख्या है।

0
जोड़ा

विचार करने के लिए दो चीजें।

1. रिकॉर्ड को संसाधित करने में कितना समय लगेगा?

यदि रिकॉर्ड प्रोसेसिंग बहुत तेज़ है, तो धागे को रिकॉर्ड देने का ओवरहेड एक बाधा बन सकता है। इस मामले में, आप रिकॉर्ड्स को बंडल करना चाहते हैं ताकि आपको उन्हें अक्सर बंद नहीं करना पड़े।

यदि रिकॉर्ड प्रोसेसिंग काफी लंबी चल रही है, तो अंतर नगण्य होगा, इसलिए सरल दृष्टिकोण (प्रति थ्रेड 1 रिकॉर्ड) शायद सबसे अच्छा है।

2. शुरू करने पर आप कितने धागे की योजना बना रहे हैं?

यदि आप थ्रेडपूल का उपयोग नहीं कर रहे हैं, तो मुझे लगता है कि आपको या तो थ्रेड की संख्या को मैन्युअल रूप से सीमित करने की आवश्यकता है, या आपको डेटा को बड़े हिस्सों में तोड़ने की आवश्यकता है। प्रत्येक रिकॉर्ड के लिए एक नया धागा शुरू करने से आपके सिस्टम को थ्रैशिंग छोड़ दी जाएगी यदि रिकॉर्ड्स की संख्या बड़ी हो जाती है।

0
जोड़ा
हां, वे उपयोगी विचार हैं। चूंकि यह एक सार्वजनिक डोमेन webservice को कॉल कर रहा है, इसलिए मुझे लगता है कि हम यह देखने के लिए कुछ परीक्षण करना चाहेंगे कि ओवरहेड नौकरी से ज्यादा है (मुझे शक है)। और हां, थ्रेडपूल का उपयोग कुछ ऐसा है जिसे हम निश्चित रूप से मानते थे।
जोड़ा लेखक Vaibhav, स्रोत