कौन सा समवर्ती कतार कार्यान्वयन मुझे जावा में उपयोग करना चाहिए?


132

JavaDocs से:

  • एक समवर्ती लाईन क्यू एक उपयुक्त विकल्प है जब कई थ्रेड एक सामान्य संग्रह तक पहुंच साझा करेंगे। यह कतार शून्य तत्वों की अनुमति नहीं देती है।
  • ArrayBlockingQueue एक क्लासिक "बाउंडेड बफर" है, जिसमें एक निश्चित आकार की सरणी उत्पादकों द्वारा सम्मिलित तत्व रखती है और उपभोक्ताओं द्वारा निकाली जाती है। यह वर्ग वेटिंग प्रोड्यूसर और कंज्यूमर थ्रेड्स ऑर्डर करने के लिए एक वैकल्पिक निष्पक्षता नीति का समर्थन करता है
  • LinkedBlockingQueue में आमतौर पर सरणी-आधारित कतारों की तुलना में उच्चतर थ्रूपुट होता है लेकिन अधिकांश समवर्ती अनुप्रयोगों में कम अनुमानित प्रदर्शन होता है।

मेरे पास 2 परिदृश्य हैं, एक को एक उपभोक्ता के साथ कई उत्पादकों (इसका उपयोग करने वाले धागे) का समर्थन करने के लिए कतार की आवश्यकता होती है और दूसरा आसपास का दूसरा रास्ता है।

मुझे समझ में नहीं आता है कि किस कार्यान्वयन का उपयोग करना है। क्या कोई समझा सकता है कि अंतर क्या हैं?

इसके अलावा, 'वैकल्पिक निष्पक्षता नीति' क्या है ArrayBlockingQueue?


1
आप प्रायोरब्लॉकिंग क्यू के बारे में पूछना भी भूल गए, जो एक आदेश को निर्दिष्ट करने के लिए उपयोगी है जिसमें धागे संसाधित होते हैं।
इगोरगानापोलस्की

जवाबों:


53

मूल रूप से उनके बीच का अंतर प्रदर्शन विशेषताओं और अवरुद्ध व्यवहार है।

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

के बीच सबसे महत्वपूर्ण अंतर LinkedBlockingQueueऔर ConcurrentLinkedQueueहै कि आप एक से एक तत्व का अनुरोध करता है, तो है LinkedBlockingQueueऔर कतार खाली है, अपने धागा जब तक वहाँ कुछ है वहाँ इंतजार करेंगे। A ConcurrentLinkedQueueखाली कतार के व्यवहार के साथ तुरंत वापस आ जाएगा।

यदि आपको अवरुद्ध करने की आवश्यकता है, तो कौन सा निर्भर करता है। जहां आपके पास कई निर्माता और एक उपभोक्ता हैं, यह ऐसा लगता है। दूसरी ओर, जहां आपके पास कई उपभोक्ता और केवल एक निर्माता हैं, आपको अवरुद्ध व्यवहार की आवश्यकता नहीं हो सकती है, और केवल उपभोक्ताओं की जांच करने में खुशी हो सकती है यदि कतार खाली है और यदि यह है तो आगे बढ़ें।


67
उत्तर भ्रामक है। LinkedBlockingQueue और ConcurrentLinkedQueue दोनों में "पोल ()" विधि है जो कतार के शीर्ष को हटाती है या अशक्त (ब्लॉक नहीं होती है) और पद्धति "ऑफ़र (ई ई)" को सम्मिलित करती है जो कतार की पूंछ में सम्मिलित होती है और ब्लॉक नहीं होती है। अंतर यह है कि केवल LinkedBlockingQueue के पास नॉन-ब्लॉकिंग ऑपरेशंस के अलावा ब्लॉकिंग ऑपरेशंस हैं - और उस विशेषाधिकार के लिए, आप उस कीमत का भुगतान करते हैं जो लिंक्डब्लॉकिंग क्यू वास्तव में कुछ लॉकिंग है। अन्य उत्तर यह बताते हैं।
नाकाबिल

123

समवर्तीलिंक्यू का मतलब है कि कोई लॉक नहीं लिया जाता (यानी कोई सिंक्रनाइज़ नहीं है (यह) या लॉकलॉक कॉल)। यह देखने के लिए संशोधनों के दौरान एक CAS - तुलना और स्वैप ऑपरेशन का उपयोग करेगा, यह देखने के लिए कि क्या सिर / पूंछ नोड अभी भी वैसा ही है जब यह शुरू हुआ था। यदि हां, तो ऑपरेशन सफल होता है। यदि सिर / पूंछ का नोड अलग है, तो यह घूम जाएगा और फिर से प्रयास करेगा।

LinkedBlockingQueue किसी भी संशोधन से पहले एक ताला लगेगा। इसलिए आपका ऑफ़र कॉल तब तक ब्लॉक रहेगा जब तक उन्हें लॉक नहीं मिल जाता। आप ऑफ़र ओवरलोड का उपयोग कर सकते हैं जो यह कहने में समय लेता है कि आप केवल एक्स को छोड़ने से पहले एक्स राशि की प्रतीक्षा करने के लिए तैयार हैं (आमतौर पर संदेश प्रकार की कतारों के लिए अच्छा है जहां संदेश मिलीसेकेंड के एक्स नंबर के बाद बासी है)।

निष्पक्षता का मतलब है कि लॉक कार्यान्वयन थ्रेड्स को व्यवस्थित रखेगा। मतलब अगर थ्रेड ए प्रवेश करता है और फिर थ्रेड बी प्रवेश करता है, थ्रेड ए को पहले लॉक मिलेगा। निष्पक्षता के साथ, यह अपरिभाषित है कि वास्तव में क्या होता है। यह सबसे अधिक संभावना है कि अगला धागा अनुसूचित हो जाएगा।

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


1
और क्या शर्तों के तहत ArrayBlockingQueue LinkedBlockingQueue से बेहतर है?
कोलोबोक

@akapelko ArrayBlockingQueue अधिक महीन दाने वाले ऑर्डर के लिए अनुमति देता है।
इगोरगानापल्स्की

2
इसका क्या अर्थ है - "यह चारों ओर घूमेगा और फिर से प्रयास करेगा।" ?
लेस्टर

9

आपके प्रश्न शीर्षक में अवरुद्ध कतारों का उल्लेख है। हालांकि, ConcurrentLinkedQueueहै एक अवरुद्ध कतार।

BlockingQueueरों हैं ArrayBlockingQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, PriorityBlockingQueue, और SynchronousQueue

इनमें से कुछ स्पष्ट रूप से अपने उद्देश्य के लिए उपयुक्त नहीं हैं ( DelayQueue, PriorityBlockingQueue, और SynchronousQueue)। LinkedBlockingQueueऔर LinkedBlockingDequeसमान हैं, सिवाय इसके कि बाद वाला एक डबल-एंडेड क्यू है (यह डेक्स इंटरफ़ेस को लागू करता है)।

चूंकि ArrayBlockingQueueआप केवल तभी उपयोगी होते हैं, जब आप तत्वों की संख्या को सीमित करना चाहते हैं, तो मैं चिपका सकता हूं LinkedBlockingQueue


मैंने शीर्षक से ब्लॉकिंग शब्द हटा दिया, धन्यवाद। मुझे देखने दें कि क्या मुझे यह मिला है, आपने जो कहा है उसका मतलब है कि लिंक्डब्लॉकिंग क्यू का उपयोग बहुस्तरीय उपभोक्ताओं में किया जा सकता है / एक ही वस्तु पर परिदृश्य का निर्माण करता है?
डेविड हॉफमैन

1
मैंने सोचा था कि ArrayBlockingQueue धागे के अधिक महीन दाने के ऑर्डर की अनुमति देता है? इसलिए इसका फायदा।
इगोरगानपोलस्की

4

ArrayBlockingQueue में कम मेमोरी फ़ुटप्रिंट है, यह तत्व नोड का पुन: उपयोग कर सकता है, लिंक्डब्लॉकिंग क्यू की तरह नहीं, जो प्रत्येक नए सम्मिलन के लिए लिंक्डब्लॉकिंग क्यू $ Node ऑब्जेक्ट बनाना है।


1
अच्छी बात! मैं ArrayBlockingQueue को LinkedBlockingQueue से अधिक पसंद करता हूं
खरबों

2
यह जरूरी सच नहीं है - अगर आपकी कतार बहुत समय खाली करने के करीब है, लेकिन बड़े बढ़ने में सक्षम होने की जरूरत है, ArrayBlockingQueueतो बहुत अधिक स्मृति पदचिह्न होगा - यह अभी भी पूरे समय में स्मृति में आवंटित एक बड़ा सरणी है, जबकि LinkedBlockingQueueजब पास खाली करने के लिए एक नगण्य स्मृति पदचिह्न होगा।
क्रीज

1
  1. SynchronousQueue(दूसरे सवाल से लिया गया )

SynchronousQueueएक हैंडऑफ़ के अधिक है, जबकि LinkedBlockingQueueसिर्फ एक तत्व की अनुमति देता है। अंतर यह है कि जब तक संबंधित कॉल नहीं होगी, तब तक put()कॉल SynchronousQueueवापस नहीं आएगी take(), लेकिन LinkedBlockingQueueआकार 1 के साथ, put()कॉल (एक खाली कतार में) तुरंत वापस आ जाएगी। यह अनिवार्य रूप से BlockingQueueकार्यान्वयन के लिए है जब आप वास्तव में एक कतार नहीं चाहते हैं (आप किसी भी लंबित डेटा को बनाए नहीं रखना चाहते हैं)।

  1. LinkedBlockingQueue( LinkedListकार्यान्वयन लेकिन सटीक रूप से नहीं JDK इसका कार्यान्वयन LinkedListतत्वों के बीच संबंध बनाए रखने के लिए स्थैतिक आंतरिक वर्ग नोड का उपयोग करता है)

लिंक्डब्लॉकिंग क्यू के लिए कंस्ट्रक्टर

public LinkedBlockingQueue(int capacity) 
{
        if (capacity < = 0) throw new IllegalArgumentException();
        this.capacity = capacity;
        last = head = new Node< E >(null);   // Maintains a underlying linkedlist. ( Use when size is not known )
}

नोड क्लास लिंक को बनाए रखने के लिए उपयोग किया जाता है

static class Node<E> {
    E item;
    Node<E> next;
    Node(E x) { item = x; }
}

३। ArrayBlockingQueue (एरे कार्यान्वयन)

ArrayBlockingQueue के लिए कंस्ट्रक्टर

public ArrayBlockingQueue(int capacity, boolean fair) 
{
            if (capacity < = 0)
                throw new IllegalArgumentException();
            this.items = new Object[capacity]; // Maintains a underlying array
            lock = new ReentrantLock(fair);
            notEmpty = lock.newCondition();
            notFull =  lock.newCondition();
}

IMHO सबसे बड़ा अंतर है ArrayBlockingQueueऔर LinkedBlockingQueueस्पष्ट है कि निर्माणकर्ता के पास अंतर्निहित डेटा संरचना एरे और अन्य लिंक्डलिस्ट हैं

ArrayBlockingQueueसिंगल-लॉक डबल कंडीशन एल्गोरिदम का उपयोग करता है और LinkedBlockingQueue"दो लॉक कतार" एल्गोरिथ्म का प्रकार है और इसमें 2 लॉक 2 स्थितियां हैं (टेकलॉक, पुटॉक)


0

ConcurrentLinkedQueue लॉक-फ्री है, LinkedBlockingQueue नहीं है। जब भी आप LinkedBlockingQueue.put () या LinkedBlockingQueue.take () का आह्वान करते हैं, तो आपको पहले लॉक का अधिग्रहण करना होगा। दूसरे शब्दों में, LinkedBlockingQueue की खराब संगति है। यदि आप प्रदर्शन की देखभाल करते हैं, तो समवर्तीलिंक्यू + लॉकस्कैपोर्ट का प्रयास करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.