मैं अपने ArrayList Thread-Safe को कैसे बनाते हैं? जावा में समस्या के लिए एक और दृष्टिकोण?


90

मेरे पास एक ArrayList है जो मैं RaceCar ऑब्जेक्ट्स को होल्ड करने के लिए उपयोग करना चाहता हूं जो थ्रेड क्लास का विस्तार करते हैं जैसे ही वे निष्पादित होते हैं। एक वर्ग, जिसे रेस कहा जाता है, एक कॉलबैक पद्धति का उपयोग करके इस ArrayList को संभालता है जिसे रेसकार ऑब्जेक्ट तब निष्पादित करता है जब इसे निष्पादित किया जाता है। कॉलबैक विधि, addFinisher (रेसकार फिनिशर), ArrayList में रेसकार ऑब्जेक्ट जोड़ता है। यह उस आदेश को देने वाला है जिसमें थ्रेड्स निष्पादन को समाप्त करते हैं।

मुझे पता है कि ArrayList सिंक्रनाइज़ नहीं है और इस प्रकार थ्रेड-सुरक्षित नहीं है। मैंने एक नए ArrayList में पास होकर और ArrayList में दिए गए Collection को असाइन करके कलेक्शंस। SynchronizedCollection (c Collection) पद्धति का उपयोग करने की कोशिश की। हालाँकि, यह मुझे एक संकलक त्रुटि देता है:

Race.java:41: incompatible types
found   : java.util.Collection
required: java.util.ArrayList
finishingOrder = Collections.synchronizedCollection(new ArrayList(numberOfRaceCars));

यहाँ प्रासंगिक कोड है:

public class Race implements RaceListener {
    private Thread[] racers;
    private ArrayList finishingOrder;

    //Make an ArrayList to hold RaceCar objects to determine winners
    finishingOrder = Collections.synchronizedCollection(new ArrayList(numberOfRaceCars));

    //Fill array with RaceCar objects
    for(int i=0; i<numberOfRaceCars; i++) {
    racers[i] = new RaceCar(laps, inputs[i]);

        //Add this as a RaceListener to each RaceCar
        ((RaceCar) racers[i]).addRaceListener(this);
    }

    //Implement the one method in the RaceListener interface
    public void addFinisher(RaceCar finisher) {
        finishingOrder.add(finisher);
    }

मुझे जो जानने की जरूरत है, क्या मैं एक सही दृष्टिकोण का उपयोग कर रहा हूं और यदि नहीं, तो मुझे अपने कोड को सुरक्षित बनाने के लिए क्या उपयोग करना चाहिए? सहायता के लिए धन्यवाद!


2
(ध्यान दें, Listइंटरफ़ेस वास्तव में मल्टीथ्रेडिंग में बहुत उपयोगी होने के लिए पर्याप्त नहीं है।)
टॉम हैटिन -

3
मैं यह बताना चाहूंगा कि, इसके बिना Collections.synchronizedList(), हमारे यहाँ एक वास्तविक दौड़ की स्थिति होगी: P
डायलन वॉटसन

इस लिंक की जाँच करें programmerzdojo.com/java-tutorials/…
rishi007bansod

जवाबों:


147

का उपयोग करें Collections.synchronizedList()

उदाहरण के लिए:

Collections.synchronizedList(new ArrayList<YourClassNameHere>())

2
धन्यवाद! मुझे यकीन नहीं है कि मैंने एक वेक्टर का उपयोग करने के लिए क्यों नहीं सोचा था क्योंकि मुझे याद है कि वे कहीं पढ़ रहे थे वे सिंक्रनाइज़ किए गए थे।
इरीसो

32
हो सकता है कि यह वर्गों के साथ काम करने वाला एक अच्छा विचार नहीं है जो कि पदावनत के रूप में परिभाषित किया गया है
frandevel

1
हालाँकि वेक्टर काफी पुराना है और इसमें कलेक्शंस-सपोर्ट की कमी है, लेकिन यह डिप्रेस्ड नहीं है। अन्य लोगों की तरह संग्रहणीय.संयंत्रित ललिस्ट () का उपयोग करना बेहतर है।
एस्टूरियो

14
-1 टिप्पणियों के लिए। वेक्टर को पदावनत नहीं किया जाता है और इसमें संग्रह समर्थन नहीं है? यह सूची लागू करता है। वेक्टर के लिए javadoc विशेष रूप से कहता है: "जावा 2 प्लेटफॉर्म v1.2 के रूप में, इस वर्ग को सूची इंटरफ़ेस को लागू करने के लिए रेट्रोफिट किया गया था, जो इसे जावा कलेक्शंस फ्रेमवर्क का सदस्य बनाता है। नए संग्रह कार्यान्वयन के विपरीत, वेक्टर सिंक्रनाइज़ किया गया है।" वेक्टर का उपयोग नहीं करने के लिए अच्छे कारण हो सकते हैं (सिंक्रनाइज़ेशन से बचना, कार्यान्वयन को बदलना), लेकिन "अप्रचलित" या "आधुनिक नहीं" होना उनमें से एक नहीं है।
बेवकूफ

1
नीचे दिए गए तरीकों का उपयोग करें: Collections.synchronizedList (सूची); Collections.synchronizedSet (सेट); Collections.synchronizedMap (नक्शा); उपरोक्त विधियां पैरामीटर के रूप में संग्रह लेती हैं और उसी प्रकार के संग्रह को वापस करती हैं जो सिंक्रनाइज़ और थ्रेड सुरक्षित हैं।
समीर काजी

35

परिवर्तन

private ArrayList finishingOrder;

//Make an ArrayList to hold RaceCar objects to determine winners
finishingOrder = Collections.synchronizedCollection(new ArrayList(numberOfRaceCars)

सेवा

private List finishingOrder;

//Make an ArrayList to hold RaceCar objects to determine winners
finishingOrder = Collections.synchronizedList(new ArrayList(numberOfRaceCars)

सूची ArrayList का एक सुपरस्क्रिप्ट है, इसलिए आपको इसे निर्दिष्ट करने की आवश्यकता है।

अन्यथा, आप जो कर रहे हैं वह ठीक लगता है। अन्य विकल्प यह है कि आप वेक्टर का उपयोग कर सकते हैं, जो सिंक्रनाइज़ किया गया है, लेकिन यह संभवतः मैं क्या करूंगा।


1
या Listशायद अधिक उपयोगी होगा। या List<RaceCar>
टॉम हॉकिन -

अच्छा बिंदु, इसे निजी बनाएं सूची finishingOrder = Collections.synchronizedList (...)
रेवरेंड गोंजो

मैंने यह कोशिश की और संकलनकर्ता अब मेरे बारे में ArrayList तरीकों को एक संग्रह पर कॉल करने की शिकायत कर रहा है: //Print out winner System.out.println("The Winner is " + ((RaceCar) finishingOrder.get(0)).toString() + "!"); यह कह रहा है कि (0) विधि नहीं मिली है। विचार?
इरीसो

मेरी टिप्पणी को हटाने और पुनः जोड़ने के बारे में क्षमा करें। मैं बैकटिक्स का उपयोग कर काम को हाइलाइट करने की कोशिश कर रहा था। मुझे उस तरह के सामान के बारे में ओसीडी मिलता है।
एरिकोसो

नहीं, यह काम नहीं करता है। यह संग्रह को किसी सूची में नहीं डालेगा: Race.java:41: असंगत प्रकार पाए गए: java.util.Collection आवश्यक: java.util.List परिष्करणकार्यकर्ता = संग्रह। SynchronizedCollection (नया ArrayList (numberOfRaceCars));
इरीसो

11

CopyOnWriteArrayList

CopyOnWriteArrayListकक्षा का उपयोग करें । यह थ्रेड सेफ वर्जन है ArrayList


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

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

7

आप गलत दृष्टिकोण का उपयोग कर रहे होंगे। सिर्फ इसलिए कि एक धागा जो एक कार को अनुकरण करता है एक और कार-सिमुलेशन धागा से पहले खत्म होता है इसका मतलब यह नहीं है कि पहले धागे को नकली दौड़ जीतनी चाहिए।

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


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

5

आप इस तरह की विधि के synchronizedलिए भी कीवर्ड का उपयोग कर सकते हैंaddFinisher

    //Implement the one method in the RaceListener interface
    public synchronized void addFinisher(RaceCar finisher) {
        finishingOrder.add(finisher);
    }

तो आप इस तरह से ArrayList ऐड मेथड थ्रेड-सेफ का इस्तेमाल कर सकते हैं।


4
ठीक है, लेकिन क्या होगा अगर आपको दो तरीके मिले: addFinisher और delFinisher? दोनों विधियाँ थ्रेड-सुरक्षित हैं लेकिन चूंकि दोनों एक ही ArrayList को एक्सेस करते हैं इसलिए आपको फिर भी परेशानी होगी।
मासी

1
@masi तब आप final Objectहर बार जब आप Collectionकिसी भी तरह से एक्सेस करते हैं , तो आप इसके बजाय केवल एक बार सिंक्रोनाइज़ करते हैं ।
mkuech

2

जब भी आप चींटी संग्रह ऑब्जेक्ट के थ्रेड थ्रेड सुरक्षित संस्करण का उपयोग करना चाहते हैं, तो java.util.concurrent * की मदद लें पैकेज । इसमें असंबद्ध संग्रह वस्तुओं के लगभग सभी समवर्ती संस्करण हैं। जैसे: ArrayList के लिए, आपके पास java.util.concurrent.CopyOnWriteArrayList है

आप Collections.synchronizedCollection (किसी भी संग्रह ऑब्जेक्ट) कर सकते हैं, लेकिन इस शास्त्रीय synchr याद रखें। तकनीक महंगी है और परफॉर्मेंस ओवरहेड के साथ आती है। java.util.concurrent। * पैकेज कम खर्चीला है और तंत्र की तरह बेहतर तरीके से प्रदर्शन का प्रबंधन करता है

कॉपी-ऑन-राइट, तुलना-और-स्वैप, लॉक, स्नैपशॉट पुनरावृत्तियों, आदि।

तो, java.util.concurrent। * पैकेज से कुछ पसंद करें


1

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

लेकिन आप अपनी Arraylist को दिए गए कोड की तरह सिंक्रनाइज़ कर सकते हैं:

Collections.synchronizedList(new ArrayList(numberOfRaceCars())); 

-1

आप ArrayList से वेक्टर प्रकार में बदल सकते हैं, जिसमें प्रत्येक विधि सिंक्रनाइज़ है।

private Vector finishingOrder;
//Make a Vector to hold RaceCar objects to determine winners
finishingOrder = new Vector(numberOfRaceCars);

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