2008-12-11 11 views
16

मुझे लगता है कि मैंसरल कतार कार्यान्वयन के बजाय आप BlockingQueue कार्यान्वयन का उपयोग कहां से करें?

से अपने प्रश्न को रेफ्रेम करूँगा सरल कतार कार्यान्वयन के बजाय आप ब्लॉकिंगक्यूयू कार्यान्वयन का उपयोग कहां करना चाहिए?

को

क्या फायदे/गति, संगामिति या अन्य गुणों की तरह विचार पहलुओं को ध्यान में रखकर कतार कार्यान्वयन से अधिक BlockingQueue का नुकसान जो जैसे अलग-अलग हो रहे हैं अंतिम तत्व तक पहुंचने का समय।

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

क्या कोई ब्लॉकिंगक्यूयू बनाम कतार बनाम सूची कार्यान्वयन के पेशेवरों और विपक्ष के बारे में चर्चा कर सकता है?

वर्तमान में मैंने इन बाइटबफर ऑब्जेक्ट्स को पकड़ने के लिए ऐरेलिस्ट का उपयोग किया है।

इन वस्तुओं को रखने के लिए मैं किस डेटा संरचना का उपयोग करूं?

उत्तर

26

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

इन तरह की स्थितियों में, यह एक निर्माता बनने के लिए बेहतर हो सकता है कि कतार पूर्ण है, और विफलता के साथ जल्दी छोड़ने के लिए। उदाहरण के लिए, निर्माता एक वेब अनुरोध हो सकता है, ऐसे उपयोगकर्ता के साथ जो बहुत लंबा इंतजार नहीं करना चाहता, और भले ही यह प्रतीक्षा करते समय कई CPU चक्रों का उपभोग नहीं करेगा, यह सॉकेट और कुछ मेमोरी जैसे सीमित संसाधनों का उपयोग कर रहा है । देने से उन कार्यों को दिया जाएगा जो समय-समय पर समाप्त होने के लिए पहले से ही एक बेहतर मौका है।


संशोधन सवाल है, जो मैं के रूप में व्याख्या कर रहा हूँ, के बारे में

"क्या एक पूल में वस्तुओं के आयोजन के लिए एक अच्छा संग्रह है?"

एक unbounded LinkedBlockingQueue कई पूल के लिए एक अच्छा विकल्प है। हालांकि, आपके पूल प्रबंधन रणनीति के आधार पर, ConcurrentLinkedQueue भी काम कर सकता है।

पूलिंग एप्लिकेशन में, अवरुद्ध "डाल" उचित नहीं है। कतार के अधिकतम आकार को नियंत्रित करना पूल प्रबंधक — का काम है यह पूल के संसाधनों को बनाने या नष्ट करने का निर्णय लेता है। पूल के ग्राहक उधार लेते हैं और पूल से संसाधन वापस करते हैं। एक नई वस्तु जोड़ना, या पूल में पहले उधारित वस्तु को वापस करना तेजी से, गैर-अवरुद्ध संचालन होना चाहिए। तो, एक बाध्य क्षमता कतार पूल के लिए एक अच्छा विकल्प नहीं है।

दूसरी ओर, पूल से ऑब्जेक्ट पुनर्प्राप्त करते समय, अधिकांश एप्लिकेशन संसाधन तक उपलब्ध होने तक प्रतीक्षा करना चाहते हैं। एक "टेक" ऑपरेशन जो कम से कम अस्थायी रूप से ब्लॉक करता है, संसाधनों के उपलब्ध होने तक "व्यस्त प्रतीक्षा" — बार-बार मतदान करने से अधिक कुशल होता है। इस मामले में LinkedBlockingQueue एक अच्छा विकल्प है। एक उधारकर्ता take के साथ अनिश्चित काल तक अवरुद्ध कर सकता है, या poll के साथ ब्लॉक करने के इच्छुक समय को सीमित कर सकता है।

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

इनमें से दोनों संग्रह एक समवर्ती आवेदन में अच्छा प्रदर्शन और उपयोग में आसानी देते हैं। गैर-समवर्ती अनुप्रयोगों के लिए, ArrayList को हरा करना मुश्किल है। यहां तक ​​कि गतिशील रूप से बढ़ने वाले संग्रहों के लिए, LinkedList के प्रति-तत्व ओवरहेड ArrayList को कुछ खाली स्लॉट के साथ प्रतिस्पर्धी स्मृति-वार रहने के लिए अनुमति देता है।

+1

धन्यवाद एरिक्सन का उपयोग अपने Queue कार्यान्वयन के बाद किया जाएगा। इसने मेरी समस्या हल कर दी है। –

2

आप बहु-थ्रेडेड परिस्थितियों में BlockingQueue देखेंगे। उदाहरण के लिए यदि आप कन्स्ट्रक्टर का उपयोग करके एक बनाना चाहते हैं तो ThreadPoolExecutor बनाने के लिए आपको पैरामीटर के रूप में BlockingQueue में पास करने की आवश्यकता है। आप निष्पादक में पारित कतार के प्रकार के आधार पर अलग-अलग कार्य कर सकते हैं।

0

BlockingQueue एक दूसरे पर निर्भर समानांतर संचालन को क्रमबद्ध करने के लिए भी उपयोगी है।

एक ठोस लाने के लिए (हालांकि कुछ हद तक अनियन्त्रित) उदाहरण के लिए, here एक वास्तविक समय रोगी कतार वेब अनुप्रयोग जहां callInPatient()registerPatientToAppointment() के साथ समानांतर में लॉन्च करने की आवश्यकता के लिए एक समानांतर परीक्षण है, लेकिन registerPatientToAppointment() तक इंतजार करने की जरूरत है callPatientInAtDoctorsOffice() निष्पादित करने से पहले पूरा हो गया है :

public class ClinicPatientQueueAppTest extends ParallelTest { 

    private static final BlockingQueue WAIT_FOR_REGISTRATION_QUEUE = new ArrayBlockingQueue(2); 

    @Test 
    public void callInPatient() { 
     loginToDoctorsOffice("user", "password"); 
     waitUntilRegistrationCompleted(); // <-- 
     callPatientInAtDoctorsOffice(); 
    } 

    @Test 
    public void registerPatientToAppointment() { 
     registerPatientAtRegistrationKiosk("Patient Peter"); 
     notifyRegistrationCompleted(); // <-- 
    } 

    private void waitUntilRegistrationCompleted() { 
     WAIT_FOR_REGISTRATION_QUEUE.take(); 
    } 

    private void notifyRegistrationCompleted() { 
     WAIT_FOR_REGISTRATION_QUEUE.put(this); 
    } 

} 
0

यह एक Queue कार्यान्वयन कि अतिरिक्त संचालन का समर्थन करता है कि करने के लिए कतार के लिए

इंतजार गैर खाली हो जाते हैं जब एक तत्व,

और

इंतजार पुन: प्राप्त करने के लिए जब एक तत्व भंडारण अंतरिक्ष कतार में उपलब्ध होने के लिए।

यदि आप कार्यक्षमता ऊपर की आवश्यकता तो इस तरह के एक अच्छा विवरण के लिए Blocking Queue

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