कैसे करें समवर्ती Linkedue का उपयोग?


95

मैं ConcurrentLinkedQueueजावा में कैसे उपयोग करूं ?
इसका उपयोग करते हुए LinkedQueue, क्या मुझे कतार में संगामिति के बारे में चिंतित होने की आवश्यकता है? या क्या मुझे सिर्फ दो तरीकों को परिभाषित करना है (एक सूची से तत्वों को वापस लेने के लिए और दूसरा सूची में तत्वों को जोड़ने के लिए)?
नोट: जाहिर है कि इन दो तरीकों को सिंक्रनाइज़ किया जाना है। सही?


संपादित करें: मैं जो करने की कोशिश कर रहा हूं वह यह है: मेरे पास एक वर्ग है (जावा में) जिसमें एक विधि कतार से आइटम निकालने के लिए और दूसरी कक्षा एक विधि के साथ आइटम को कतार में जोड़ने के लिए है। सूची से जोड़े और पुनर्प्राप्त किए गए आइटम मेरे अपने वर्ग की वस्तुएं हैं।

एक और सवाल: क्या मुझे इसे हटाने की विधि में करने की आवश्यकता है:

while (queue.size() == 0){ 
  wait(); 
  queue.poll();
}

मेरे पास केवल एक उपभोक्ता और एक निर्माता है।


Mt प्रश्न की प्रतिक्रिया के लिए धन्यवाद। जो मैं करने की कोशिश कर रहा हूं वह यह है: मेरे पास एक तरीका है (जावा में) एक विधि के साथ कतार से वस्तुओं को पुनः प्राप्त करने के लिए और एक अन्य वर्ग के साथ एक पंक्ति में आइटम जोड़ने के लिए। सूची से जोड़े और पुनर्प्राप्त किए गए आइटम मेरे अपने वर्ग की वस्तुएं हैं।
रिकार्डो फेलगुइरास

2
आपको अपने प्रश्न को संपादित करना चाहिए और इस स्पष्टीकरण को प्रश्न में ही डालना चाहिए।
आदम जास्कविकेज़

जवाबों:


156

नहीं, विधियों को सिंक्रनाइज़ करने की आवश्यकता नहीं है, और आपको किसी भी तरीके को परिभाषित करने की आवश्यकता नहीं है; वे पहले से ही समवर्ती लिपि क्यू में हैं, बस उनका उपयोग करें। ConcurrentLinkedQueue उन सभी लॉकिंग और अन्य ऑपरेशनों को करता है जिनकी आपको आंतरिक आवश्यकता होती है; आपका निर्माता (s) कतार में डेटा जोड़ता है, और आपके उपभोक्ता इसके लिए मतदान करते हैं।

सबसे पहले, अपनी कतार बनाएं:

Queue<YourObject> queue = new ConcurrentLinkedQueue<YourObject>();

अब, जहाँ भी आप अपने निर्माता / उपभोक्ता वस्तुओं का निर्माण कर रहे हैं, कतार में गुज़ारें ताकि उनके पास अपनी वस्तुएं रखने के लिए कहीं न कहीं (आप इसके लिए एक सेटर का उपयोग कर सकें, बल्कि मैं इस तरह की चीज़ को एक निर्माता में करना पसंद करता हूँ):

YourProducer producer = new YourProducer(queue);

तथा:

YourConsumer consumer = new YourConsumer(queue);

और अपने निर्माता में इसके लिए सामान जोड़ें:

queue.offer(myObject);

और अपने उपभोक्ता में सामान निकाल लें (यदि कतार खाली है, तो पोल () शून्य हो जाएगा, इसलिए इसे देखें):

YourObject myObject = queue.poll();

अधिक जानकारी के लिए Javadoc देखें

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

यदि आपको कतार के खाली होने की प्रतीक्षा में ब्लॉक करने की आवश्यकता है, तो आप संभवतः एक लिंक्डब्लॉकिंग क्यू का उपयोग करना चाहते हैं , और ले () विधि का उपयोग कर सकते हैं। हालाँकि, LinkedBlockingQueue की अधिकतम क्षमता (Integer.MAX_VALUE के लिए डिफ़ॉल्ट है, जो दो बिलियन से अधिक है) और इस प्रकार आपकी परिस्थितियों के आधार पर उपयुक्त हो सकती है या नहीं भी।

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

Queue<YourObject> queue = Collections.synchronizedList(new LinkedList<YourObject>());

इसका एक प्लस यह है कि यह इंस्टेंस (कतार) पर लॉक होता है, इसलिए आप कंपोजिट ऑपरेशन्स की एटोमेसी (जैसा कि जेरेड द्वारा समझाया गया है) सुनिश्चित करने के लिए कतार पर सिंक्रोनाइज़ कर सकते हैं। आप इसे किसी समवर्ती विधि से नहीं कर सकते, क्योंकि सभी ऑपरेशन इंस्टेंस पर लॉक किए बिना किए जाते हैं (java.util.concurrent.atomic वैरिएबल का उपयोग करके)। यदि कतार खाली है तो आपको इसे करने की आवश्यकता नहीं होगी, क्योंकि कतार खाली होने पर पोल () बस शून्य हो जाएगा, और पोल () परमाणु है। यह देखने के लिए जांचें कि क्या पोल () शून्य है। यदि यह करता है, प्रतीक्षा करें (), तो फिर से प्रयास करें। चाबी लगाने की जरूरत नहीं।

आखिरकार:

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

BlockingQueue<YourObject> queue = new LinkedBlockingQueue<YourObject>();

queue.put(myObject); // Blocks until queue isn't full.

YourObject myObject = queue.take(); // Blocks until queue isn't empty.

बाकी हर कोई एक जैसा है। रखो शायद अवरुद्ध नहीं होगा, क्योंकि आप दो बिलियन ऑब्जेक्ट को कतार में रखने की संभावना नहीं रखते हैं।


आपके प्रतिक्रिया के लिए धन्येवाद। एक और प्रश्न: क्या मुझे इसे हटाने की विधि में करने की आवश्यकता है: जबकि (कतार।) (= = 0) प्रतीक्षा करें (); queue.poll ();
रिकार्डो फेलगुइरास

मैं जवाब दूंगा कि मेरे जवाब को संपादित करें, क्योंकि यह बहुत महत्वपूर्ण है।
एडम जस्कविज़

जैसा कि एक अन्य प्रश्न में भ्रम पैदा करता है , Collection.synchronizedListवह रिटर्न देता है Listजो लागू नहीं होता है Queue
टॉम हॉल्टिन -

ConcurrentLinkedQueueनिर्माता उपभोक्ता के लिए @AdamJaskiewicz एक अच्छा विचार है, मैं इस पोस्ट का उल्लेख कर रहा हूँ stackoverflow.com/questions/1426754/…
rd22

37

यह काफी हद तक एक और प्रश्न का दोहराव है

यहाँ उस उत्तर की धारा है जो इस प्रश्न के लिए प्रासंगिक है:

अगर मुझे java.util.ConcurrentLinkedQueue का उपयोग करना है तो क्या मुझे अपना सिंक्रोनाइज़ेशन करने की आवश्यकता है?

समवर्ती संग्रहों पर परमाणु संचालन आपके लिए सिंक्रनाइज़ हैं। दूसरे शब्दों में, कतार में प्रत्येक व्यक्ति को आपके हिस्से पर किसी भी कार्रवाई के बिना थ्रेड-सुरक्षित की गारंटी दी जाती है। थ्रेड-सेफ़ की गारंटी नहीं दी जाती है, जो आपके द्वारा किए गए किसी भी ऑपरेशन को गैर-परमाणु हैं।

उदाहरण के लिए, यह आपकी ओर से बिना किसी कार्रवाई के थ्रेडसेफ़ है:

queue.add(obj);

या

queue.poll(obj);

तथापि; कतार में गैर-परमाणु कॉल स्वचालित रूप से थ्रेड-सुरक्षित नहीं होते हैं। उदाहरण के लिए, निम्नलिखित ऑपरेशन स्वचालित रूप से थ्रेडसेफ़ नहीं हैं :

if(!queue.isEmpty()) {
   queue.poll(obj);
}

यह अंतिम एक थ्रेडसेफ़ नहीं है, क्योंकि यह बहुत संभव है कि समय के बीच इस्मिप्ट कहा जाता है और समय पोल कहा जाता है, अन्य थ्रेड्स ने कतार से आइटम को जोड़ा या हटा दिया होगा। इसे करने का थ्रेडसेफ़ तरीका इस प्रकार है:

synchronized(queue) {
    if(!queue.isEmpty()) {
       queue.poll(obj);
    }
}

फिर से ... कतार में परमाणु कॉल स्वचालित रूप से थ्रेड-सुरक्षित होते हैं। गैर-परमाणु कॉल नहीं हैं।


1
एकमात्र सामान्य उपयोग जो मैं कर सकता हूं, वह तब तक अवरुद्ध है जब तक कि कतार गैर-रिक्त न हो। क्या ब्लॉकिंग क्यू (कार्यान्वयन () परमाणु और ब्लॉकों के कार्यान्वयन का उपयोग करके बेहतर नहीं होगा) जब तक कि उपभोग करने के लिए कुछ न हो)?
एडम जस्कविज़

6
साथ ही आपको इससे सावधान रहने की जरूरत है। सिंक्रोनाइज़िस्ट के विपरीत, कॉन्ट्रालेंटलिंकड्यूक्यू अपने आप में सिंक्रोनाइज़ नहीं करता है, इसलिए आपके कोड में यह तब भी होगा कि जब आप अपने सिंक्रोनाइज़्ड ब्लॉक में हों तो कतार के लिए एक प्रोड्यूसर को पेशकश करना संभव होगा।
एडम जस्कविज़

आप क्यों पंक्तिबद्ध करेंगे ।isEmpty () और queue.poll ()? क्या आप केवल चुनाव नहीं कर सकते हैं और जाँच सकते हैं कि क्या परिणाम शून्य है? (मेरी समझ यह है कि यदि आप एक खाली कतार मतदान करते हैं तो यह अशक्त हो जाता है)
AjahnCharles

मैं अंतिम कोड ब्लॉक को छोड़कर आपके कोड में सब कुछ से सहमत हूं। समवर्तीLInkedQueue पर सिंक्रनाइज़ करना आपको कुछ भी गारंटी नहीं देता है क्योंकि अन्य कॉल सिंक्रनाइज़ नहीं हैं। इसलिए आपके "isEmpty ()" और "poll (...)" के बीच एक और धागे से "जोड़ने (..)" हो सकता है, भले ही आपने इस धागे को सिंक्रनाइज़ किया हो
Klitos G.

6

पहले तत्व को प्राप्त करने के लिए पोल का उपयोग करें , और एक नया अंतिम तत्व जोड़ने के लिए जोड़ें। यही है, कोई तुल्यकालन या कुछ और।


6

जब आप कतार में सब कुछ उपभोग करने की कोशिश कर रहे हैं तो शायद यही है जो आप धागा सुरक्षा और "अति सुंदरता" के संदर्भ में देख रहे हैं:

for (YourObject obj = queue.poll(); obj != null; obj = queue.poll()) {
}

यह गारंटी देगा कि आप कतार के खाली होने पर छोड़ देते हैं, और जब तक आप खाली नहीं होते तब तक आप इसे बंद कर देते हैं।


एक कतार को खाली करने के लिए बहुत उपयोगी है। धन्यवाद।
डेविलकोड

2

ConcurentLinkedQueue एक बहुत ही कुशल प्रतीक्षा / लॉक मुक्त कार्यान्वयन है (संदर्भ के लिए javadoc देखें), इसलिए न केवल आपको सिंक्रनाइज़ करने की आवश्यकता नहीं है, लेकिन कतार कुछ भी लॉक नहीं करेगी, इस प्रकार लगभग एक गैर सिंक्रनाइज़ेशन के रूप में तेजी से हो रहा है (थ्रेड नहीं) सुरक्षित) एक।


1

बस इसका उपयोग करें क्योंकि आप एक गैर-समवर्ती संग्रह करेंगे। समवर्ती [संग्रह] कक्षाएं नियमित संग्रह को लपेटती हैं ताकि आपको एक्सेस को सिंक्रनाइज़ करने के बारे में सोचना न पड़े।

संपादित करें: ConcurrentLinkedList वास्तव में केवल एक आवरण नहीं है, बल्कि एक बेहतर समवर्ती कार्यान्वयन है। किसी भी तरह से, आपको सिंक्रनाइज़ेशन के बारे में चिंता करने की ज़रूरत नहीं है।


समवर्तीलिखित क्यू नहीं है। यह विशेष रूप से कई उत्पादकों और उपभोक्ताओं द्वारा समवर्ती पहुंच के लिए जमीन से बनाया गया है। कलेक्शंस
रैसलर्स

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