2015-04-30 4 views
19

(HashMap $ नोड HashMap $ TreeNode में ढाला नहीं जा सकता है) stackoverflow पर पूछा एक और सवाल के बाद, (Java- Why this program not throwing concurrent Modification exception) मैं HashMap के साथ प्रयोग करने शुरू कर दिया। यहाँ कोड की कुछ लाइनें जो मैंने लिखा हैं:अजीब HashMap अपवाद

import java.util.HashMap; 
import java.util.Random; 

public class Concurrency { 
    public static void putEntriesToMap(HashMap<String, String> hashMap) { 
     for (int count = 0; count < 10000; count++) { 
      hashMap.put(Integer.toString(count), Integer.toString(count)); 
      Random random = new Random(); 
      if (random.nextBoolean()) { 
       hashMap.remove(count + ""); 
      } 
     } 
    } 

    public static void main(String[] args) throws InterruptedException { 
     final HashMap<String, String> hashMap = new HashMap<String, String>(); 
     Thread t1 = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       putEntriesToMap(hashMap); 
      } 
     }); 

     Thread t2 = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       putEntriesToMap(hashMap); 
      } 
     }); 
     t1.start(); 
     t2.start(); 
     t1.join(); 
     t2.join(); 
    } 
} 

एक बार (लगभग 20 में से 1 रन), जब इस कोड को क्रियान्वित करने, मैं

Exception in thread "Thread-0" Exception in thread "Thread-1" java.lang.ClassCastException: java.util.HashMap$Node cannot be cast to java.util.HashMap$TreeNode 
    at java.util.HashMap$TreeNode.moveRootToFront(HashMap.java:1819) 
    at java.util.HashMap$TreeNode.treeify(HashMap.java:1936) 
    at java.util.HashMap.treeifyBin(HashMap.java:771) 
    at java.util.HashMap.putVal(HashMap.java:643) 
    at java.util.HashMap.put(HashMap.java:611) 
    at Concurrency.putEntriesToMap(Concurrency.java:9) 
    at Concurrency$1.run(Concurrency.java:27) 
    at java.lang.Thread.run(Thread.java:745) 

इस मिल पर, तथापि, अजीब लगता है मेरे लिए, क्योंकि ऐसा लगता है कि यह आंतरिक हैश मैप त्रुटि है। मुझे पता है कि concurrency सही ढंग से का उपयोग नहीं किया जाता है, लेकिन यह उद्देश्य पर किया जाता है।

मैंने अपवाद को Google पर करने का प्रयास किया, लेकिन मुझे लगभग कोई जानकारी नहीं मिली।

क्या आप भी एक ही अपवाद का पुनरुत्पादन कर सकते हैं?

मैं उपयोग कर रहा हूँ ओरेकल JDK 1.8.0_40

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

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

+3

यह "सरलता का सही ढंग से उपयोग नहीं किया जाता है" का केवल परिणाम है - 'हैश मैप' को बाहरी सिंक को थ्रेड-सुरक्षित होने की आवश्यकता है। –

+0

संभव है, जब आप विभिन्न धागे के बीच सिंक्रनाइज़ नहीं करते हैं, तो सवाल क्या है? –

+0

इसके बजाय समवर्ती पैकेज से संग्रह का उपयोग करें: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentMap.html – Beri

उत्तर

9

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

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