क्या जावा के JDK में समवर्ती सूची है?


277

मैं एक समवर्ती सूची उदाहरण कैसे बना सकता हूं, जहां मैं सूचकांक द्वारा तत्वों का उपयोग कर सकता हूं? क्या JDK का कोई वर्ग या कारखाना तरीका है जिसका मैं उपयोग कर सकता हूं?


28
रचनात्मक क्यों नहीं? कई प्रस्तावित CopyOnWriteArrayList .Net में नहीं पाया जाता है। आप कह सकते हैं कि दोनों प्रश्न एक-दूसरे से संबंधित हैं, लेकिन इस एक को बंद करने के लिए नहीं !!!
एलिकएल्ज़िन-किलाका

1
मुझे पता नहीं है कि जर्रॉड रॉबर्सन को यह क्यों लगता है कि यह एक अच्छा विचार था कि स्टेपहान द्वारा किए गए विस्तृत संपादन को ले लिया जाए और उन्हें मूल, खराब-आधारित प्रश्नों पर वापस लौटा दिया जाए। जारोड का जवाब अभी भी पूरी तरह स्वीकार्य है। वास्तव में, CopyOnWriteArrayList JDK में एकमात्र समवर्ती वर्ग कार्यान्वयन सूची है। हैरान रह गए ...
मैट पासेल

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

1
/ locked/ closed/ पिछली टिप्पणी

8
इस प्रश्न को बंद करने का कोई कारण नहीं है। यह जेडीके में कक्षाओं के बारे में पूछता है, जो कि पुस्तकालय की खोज करने जैसा कुछ नहीं है; यह जावा का आधार है।
Maaartinus

जवाबों:


175

Java.util.concurrent में एक समवर्ती सूची कार्यान्वयन है । CopyOnWriteArrayList विशेष रूप से।


84
ध्यान दें कि यह पूरी सूची को हर प्रविष्टि पर कॉपी करता है, इसलिए यह अक्सर अक्षम है।
dfrankow

22
@dfrankow लेकिन अगर आप अपडेट कर रहे हैं, तो इससे अधिक पुनरावृति होने पर यह अधिक कुशल हो सकता है ।
b1nary.atr0phy

यहाँ दिखाए गए अनुसार अच्छा काम नहीं करता है। मेरे पास इसके अपवाद भी हैं फिर भी मैं इसकी addAll पद्धति का उपयोग करता हूं और स्ट्रीम का उपयोग करके इसे पढ़ता हूं। stackoverflow.com/questions/1527519/…
devshsh

166

यदि आप अनुक्रमणिका-आधारित पहुंच के बारे में परवाह नहीं करते हैं और सूची के सम्मिलन-क्रम-संरक्षण विशेषताओं को चाहते हैं, तो आप एक java.util.concurrent.ConcurrentLinkedQueue पर विचार कर सकते हैं । चूंकि यह पूरी तरह से लागू हो जाता है, एक बार जब आप सभी आइटम जोड़ना समाप्त कर लेते हैं, तो आप सिंटैक्स के लिए बढ़ाया का उपयोग करके सामग्री पर लूप कर सकते हैं:

Queue<String> globalQueue = new ConcurrentLinkedQueue<String>();

//Multiple threads can safely call globalQueue.add()...

for (String href : globalQueue) {
    //do something with href
}

4
मुझे लगता है कि कथन के लिए सरलीकृत ( :) को फॉर्चेक
AlikElzin-kilaka

2
@ AlikElzin-kilaka तुम सही हो। मुझे लगता है कि नाम ने मुझे हमेशा परेशान किया है, क्योंकि वास्तविक वाक्यविन्यास में "प्रत्येक" शब्द शामिल नहीं है, लेकिन मैं आधिकारिक नाम का उपयोग करने के लिए उत्तर को अपडेट करूंगा। :)
मैट पासेल

3
@ AlikElzin-kilaka Nitpicking, लेकिन जेएलएस संस्करण 8 के अनुसार इसे "बयान के लिए बढ़ाया" कहा जाता है। जावा ट्यूटोरियल में भी ऐसा ही है ।
रोलैंड

1
@ रोलैंड निश्चित रूप से नाइटपैकिंग नहीं है। जावा में "प्रत्येक के लिए" और "बढ़ाया" के बीच एक अंतर है (अब)।
hfontanez

2
@ रोलैंड अप्रत्यक्ष रूप से। मेरा मानना ​​है कि उन्होंने Stream.forEach के बीच भ्रम को खत्म करने के लिए "प्रत्येक लूप के लिए" को "बढ़ाया" का नाम दिया और जिसे अब बढ़ाया के रूप में जाना जाता है।
hfontanez

128

आप बहुत अच्छी तरह से उपयोग कर सकते हैं Collections.synchronizedList (सूची) यदि आप सभी की जरूरत है सरल मंगलाचरण तुल्यकालन है:

 List<Object> objList = Collections.synchronizedList(new ArrayList<Object>());

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

6
IMO, asing a के Vectorबजाय अधिक सीधा है Collections.synchronizedList(new ArrayList<Object>())
Stephan

8
सिंक्रोनिस्ट का परिणाम "सिंक्रनाइज़" है, लेकिन "समवर्ती" नहीं है।
कनागावेलु सुगुमार

46

क्योंकि स्थिति को प्राप्त करने और दिए गए स्थान से तत्व प्राप्त करने के कार्य को स्वाभाविक रूप से कुछ लॉकिंग की आवश्यकता होती है (आप उन दोनों कार्यों के बीच सूची में संरचनात्मक परिवर्तन नहीं कर सकते हैं)।

समवर्ती संग्रह का बहुत विचार यह है कि प्रत्येक ऑपरेशन अपने आप में परमाणु है और इसे स्पष्ट लॉकिंग / सिंक्रनाइज़ेशन के बिना किया जा सकता है।

इसलिए nकिसी दिए गए स्थान से तत्व को Listपरमाणु ऑपरेशन के रूप में प्राप्त करना उस स्थिति में बहुत अधिक मायने नहीं रखता है जहां समवर्ती पहुंच का अनुमान है।


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

1
बहुत अच्छी बात है। लेकिन जिस ओपी का उपयोग किया जा रहा है, उसकी सूची बहुत विशिष्ट उपयोग हो सकती है। उदाहरण के लिए, यह समवर्ती वातावरण में भरा जा सकता है, फिर "लॉक" (जो भी इसका मतलब है) और फिर सूचकांक द्वारा सुरक्षित रूप से एक्सेस किया जा सकता है। इसलिए, ऐसी सूची को भरने के पहले चरण में अभी भी एक थ्रेड-सुरक्षित कार्यान्वयन की आवश्यकता होगी। दुर्भाग्य से, ओपी इस बारे में विशिष्ट नहीं था कि जिस सूची की वह तलाश कर रहा है, उसका उपयोग कैसे किया जाएगा।
igor.zh

13

आपके पास ये विकल्प हैं:

  • Collections.synchronizedList(): आप किसी भी Listकार्यान्वयन ( या ArrayList, LinkedList3-पार्टी सूची) को लपेट सकते हैं । हर विधि (पढ़ने और लिखने) तक पहुंच का उपयोग करके संरक्षित किया जाएगा synchronizediterator()लूप के लिए उपयोग या बढ़ाया जाने पर, आपको मैन्युअल रूप से सिंक्रनाइज़ करना होगा; पुनरावृति करते समय, अन्य सूत्र पढ़ने से भी पूरी तरह से अवरुद्ध होते हैं। आप प्रत्येक hasNextऔर nextकॉल के लिए अलग से सिंक्रनाइज़ भी कर सकते हैं, लेकिन तब ConcurrentModificationExceptionसंभव है।

  • CopyOnWriteArrayList: यह संशोधित करना महंगा है, लेकिन पढ़ने के लिए प्रतीक्षा-मुक्त है। Iterators कभी नहीं फेंकते हैं ConcurrentModificationException, वे पुनरावृति के क्षण में सूची का एक स्नैपशॉट वापस करते हैं, भले ही सूची पुनरावृत्ति करते समय किसी अन्य थ्रेड द्वारा संशोधित हो। बार-बार अद्यतन सूचियों के लिए उपयोगी। addAllअपडेट के लिए जैसे बल्क ऑपरेशन्स को प्राथमिकता दी जाती है - आंतरिक सरणी को कई बार कम कॉपी किया जाता है।

  • Vector: बहुत पसंद है synchronizedList, लेकिन पुनरावृत्ति भी सिंक्रनाइज़ है। हालाँकि, ConcurrentModificationExceptionपुनरावृत्तियाँ फेंक सकते हैं , यदि वेक्टर पुनरावृत्ति करते समय किसी अन्य थ्रेड द्वारा संशोधित किया गया हो।

अन्य विकल्प:

  • Collections.unmodifiableList(): लॉक-फ़्री, थ्रेड-सुरक्षित, लेकिन गैर-परिवर्तनीय
  • Queueया Dequeएक विकल्प हो सकता है यदि आप सूची के सिरों पर केवल जोड़ / हटाते हैं और सूची को पुनरावृत्त करते हैं। सूचकांक द्वारा कोई पहुंच नहीं है और मनमाने स्थानों पर कोई जोड़ / हटाने नहीं है। बेहतर प्रदर्शन और बेहतर समवर्ती पहुंच के साथ उनके कई समवर्ती कार्यान्वयन हैं, लेकिन यह इस प्रश्न के दायरे से परे है। आप JCTools पर भी एक नज़र डाल सकते हैं , उनमें एकल उपभोक्ता या एकल निर्माता के लिए विशेष प्रदर्शन कतार कार्यान्वयन शामिल हैं।

4

यहां छवि विवरण दर्ज करें

CopyOnWriteArrayList ArrayList का एक थ्रेड-सुरक्षित वैरिएंट है जिसमें सभी म्यूटेटिव ऑपरेशंस (ऐड, सेट, और इसी तरह) को अंतर्निहित एरे की एक नई कॉपी बनाकर लागू किया जाता है।

CopyOnWriteArrayList सिंक्रोनाइज़्ड लिस्ट इम्प्लीमेंट्स लिस्ट इंटरफेस का एक समवर्ती विकल्प है और इसके java.util.concurrent packageand के थ्रेड-सेफ कलेक्शन का हिस्सा है।

public class CopyOnWriteArrayList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable

CopyOnWriteArrayList विफल-सुरक्षित है और जब सम्‍मिलित नहीं किया जाता है तो समवर्तीModificationException को फेंक नहीं देता है जब अंतर्निहित CopyOnWriteArrayList Iteration के दौरान संशोधित होता है ArrayList की एक अलग प्रति का उपयोग करें।

यह आमतौर पर बहुत महंगा है क्योंकि कॉपी एरे में हर अपडेट ऑपरेशन में एक क्लोन कॉपी बनाई जाएगी। CopyOnWriteArrayList केवल लगातार पढ़े जाने वाले ऑपरेशन के लिए सबसे अच्छा विकल्प है।

/**
         * Returns a shallow copy of this list.  (The elements themselves
         * are not copied.)
         *
         * @return a clone of this list
         */
        public Object clone() {
            try {
                @SuppressWarnings("unchecked")
                CopyOnWriteArrayList<E> clone =
                    (CopyOnWriteArrayList<E>) super.clone();
                clone.resetLock();
                return clone;
            } catch (CloneNotSupportedException e) {
                // this shouldn't happen, since we are Cloneable
                throw new InternalError();
            }
        }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.