2009-08-19 14 views
100

जावाडोक से:जावा कतार कार्यान्वयन, कौन सा?

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

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

मैं समझ नहीं कर रहा हूँ कि क्या मैं ConcurrentLikedQueue या अन्य लोगों (सरणी या linkedlist कार्यान्वयन) का उपयोग करना चाहिए। Wherent 'यह सभी कार्यान्वयन समवर्ती माना जाना चाहिए? मेरा मतलब है, किसी ने मुझसे व्याख्या कर सकते हैं ConcurrentLikedQueue और LinkedBlockingQueue के बीच अंतर क्या है?

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

+4

क्या आप वाकई यह एक समुदाय विकी होना चाहिए? ये प्रश्न ध्वनि की तरह लगता है कि उनके पास एक निश्चित उत्तर है। मैं गलत हो सकता था ... –

+1

@ एडम, धन्यवाद, आप कठोर हैं, आमतौर पर मैंने इसे कॉम्यूनिटी विकी के रूप में छोड़ दिया क्योंकि मैंने लोगों को अपनी अंग्रेजी को सही करने के रूप में देखा क्योंकि यह सामान्य रूप से ठीक नहीं है। लेकिन अब ऐसा लगता है कि साइट मुझे 'कॉम्यूनिटी विकी' चेकबॉक्स को पूर्ववत करने की अनुमति नहीं देती है –

+2

@ डेविड: लोग अभी भी आपके प्रश्न को संपादित कर सकते हैं भले ही यह एक समुदाय विकी न हो। जब कोई प्रश्न एक समुदाय विकी होता है, तो उत्तर देने वाले लोगों में से कोई भी प्रतिष्ठा अंक प्राप्त नहीं करेगा (भले ही अन्य उत्तर उत्तर दें)। उम्मीद है कि यह भविष्य के लिए चीजों को साफ़ करता है। :) –

उत्तर

36

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

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

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

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

+45

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

7

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

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

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

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

+0

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

+1

मैंने सोचा कि ArrayBlockingQueue धागे के अधिक सुगंधित आदेश के लिए अनुमति देता है? इसलिए इसका लाभ। –

92

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

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

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

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

+2

महान उत्तर जो वास्तव में मतभेदों को समझाता है! कुडोस! – Nakedible

+1

और किन स्थितियों के तहत ArrayBlockingQueue LinkedBlockingQueue से बेहतर है? – kolobok

+0

@akapelko ArrayBlockingQueue अधिक बढ़िया ऑर्डरिंग की अनुमति देता है। –

3

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

+1

अच्छा बिंदु! मैं LinkedBlockingQueue – trillions

+1

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

1
  1. SynchronousQueue (एक और question से लिया)

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

2। LinkedBlockingQueue LinkedBlockingQueue

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; } 
} 

रखरखाव के लिए प्रयुक्त (LinkedList कार्यान्वयन लेकिन LinkedList की नहीं वास्तव में JDK कार्यान्वयन यह स्थिर भीतरी वर्ग नोड तत्वों के बीच लिंक बनाए रखने के लिए उपयोग करता है) 3।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 बीच सबसे बड़ा अंतर निर्माता एक है अंतर्निहित डेटा संरचना सरणी और अन्य linkedlist से स्पष्ट है।

ArrayBlockingQueue single-lock double condition algorithm उपयोग करता है और LinkedBlockingQueue "दो ताला कतार" एल्गोरिथ्म के संस्करण है और यह 2 ताले 2 की स्थिति (takeLock, putLock)

+0

मेरे उत्तर में अधिक जानकारी जोड़ा गया। – Vipin

0

ConcurrentLinkedQueue ताला मुक्त है, LinkedBlockingQueue नहीं है। हर बार जब आप LinkedBlockingQueue.put() या LinkedBlockingQueue.take() का आह्वान करते हैं, तो आपको पहले लॉक प्राप्त करने की आवश्यकता होती है। दूसरे शब्दों में, LinkedBlockingQueue में खराब समरूपता है। यदि आप प्रदर्शन की परवाह करते हैं, तो ConcurrentLinkedQueue + LockSupport आज़माएं।

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