10

मैं जो प्रश्न पूछ रहा हूं वह Difference between StringBuilder and StringBuffer से संबंधित है लेकिन समान नहीं है। मैं देखना चाहता हूं कि वास्तव में क्या होता है यदि एक स्ट्रिंगबिल्डर एक ही समय में दो धागे द्वारा संशोधित किया जाता है।स्ट्रिंगबिल्डर कई धागे द्वारा संशोधित

मैं निम्नलिखित वर्गों ने लिखा है:

public class ThreadTester 
{ 
    public static void main(String[] args) throws InterruptedException 
    { 
     Runnable threadJob = new MyRunnable(); 
     Thread myThread = new Thread(threadJob); 
     myThread.start(); 

     for (int i = 0; i < 100; i++) 
     { 
      Thread.sleep(10); 
      StringContainer.addToSb("a"); 
     } 

     System.out.println("1: " + StringContainer.getSb()); 
     System.out.println("1 length: " + StringContainer.getSb().length()); 
    } 
} 

public class MyRunnable implements Runnable 
{ 
    @Override 
    public void run() 
    { 
     for (int i = 0; i < 100; i++) 
     { 
      try 
      { 
       Thread.sleep(10); 
      } 
      catch (InterruptedException e) 
      { 
       e.printStackTrace(); 
      } 
      StringContainer.addToSb("b"); 
     } 

     System.out.println("2: " + StringContainer.getSb()); 
     System.out.println("2 length: " + StringContainer.getSb().length()); 
    } 
} 

public class StringContainer 
{ 
    private static final StringBuffer sb = new StringBuffer(); 

    public static StringBuffer getSb() 
    { 
     return sb; 
    } 

    public static void addToSb(String s) 
    { 
     sb.append(s); 
    } 
} 

शुरू में मैं StringContainer में एक StringBuffer रखा। चूंकि StringBuffer एक समय में धागे की सुरक्षित, है, केवल एक धागा इसे करने के लिए जोड़ सकते हैं, ताकि उत्पादन अनुरूप है - या तो दोनों धागे की तरह, 200 के रूप में बफर की लंबाई सूचना:

1: abababababababababbaabababababababbaababababababababababababbabaabbababaabbaababababbababaabbababaabababbaabababbababababaababababababababbababaabbaababbaababababababbaababbababaababbabaabbababababaab 
1 length: 200 
2: abababababababababbaabababababababbaababababababababababababbabaabbababaabbaababababbababaabbababaabababbaabababbababababaababababababababbababaabbaababbaababababababbaababbababaababbabaabbababababaab 
2 length: 200 

या उनमें से एक 199 और अन्य 200, की तरह सूचना:

2: abbabababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab 
2 length: 199 
1: abbababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa 
1 length: 200 

महत्वपूर्ण यह है कि पिछले धागा रिपोर्ट 200

की लंबाई अब पूरा करने के लिए है, मैं StringContainer StringBuffer के बजाय यानी

एक StringBuilder करने के लिए परिवर्तित
public class StringContainer 
{ 
    private static final StringBuilder sb = new StringBuilder(); 

    public static StringBuilder getSb() 
    { 
     return sb; 
    } 

    public static void addToSb(String s) 
    { 
     sb.append(s); 
    } 
} 

मुझे उम्मीद है कि कुछ लिखने को अधिक लिखित होने की उम्मीद है, जो हो रहा है। लेकिन StringBuilder और लंबाई की सामग्री को कभी कभी मेल नहीं खाते:

1: ababbabababaababbaabbabababababaab 
1 length: 137 
2: ababbabababaababbaabbabababababaab 
2 length: 137 

आप देख सकते हैं मुद्रित सामग्री केवल 34 वर्ण है, लेकिन लंबाई 137 है क्यों हो रहा है के रूप में? -

@Extreme Coders मैं बस एक और परीक्षण चालन किया:

2: ababbabababaabbababaabbababaababaabbaababbaaababbaabbabbabbabababbabababbbabbbbbabababbaabababbabaabaaabaababbaabaababababbaabbbabbbbbababababbababaab 
1: ababbabababaabbababaabbababaababaabbaababbaaababbaabbabbabbabababbabababbbabbbbbabababbaabababbabaabaaabaababbaabaababababbaabbbabbbbbababababbababaab 
1 length: 150 
2 length: 150 

जावा संस्करण: 1.6.0_45 और मैं ग्रहण संस्करण का उपयोग कर रहा: वेब डेवलपर्स के लिए ग्रहण जावा ईई आईडीई। संस्करण: जूनो सेवा रिलीज़ 2 बिल्ड आईडी: 20130225-0426

अद्यतन 1: मैं इस बाहर ग्रहण भाग गया और अब वे मिलान हो रहे हैं, लेकिन मैं कभी कभी ArrayIndexOutOfBoundsException हो रही है:

$ java -version 
java version "1.6.0_27" 
OpenJDK Runtime Environment (IcedTea6 1.12.5) (6b27-1.12.5-0ubuntu0.12.04.1) 
OpenJDK Server VM (build 20.0-b12, mixed mode) 

$ java ThreadTester 
1: ababbbbbabbabababababaababbaabbbaabababbbababbabababbabbababbbbbbabaabaababbbbbbabbbbbaabbaaabbbbaabbbababababbbbabbababab 
1 length: 123 
2: ababbbbbabbabababababaababbaabbbaabababbbababbabababbabbababbbbbbabaabaababbbbbbabbbbbaabbaaabbbbaabbbababababbbbabbababab 
2 length: 123 

$ java ThreadTester 
2: abbabaabbbbbbbbbababbbbbabbbabbbabaaabbbbbbbabababbbbbbbbbabbbbbbbababababbabbbbaabbbaaabbabaaababaaaabaabbaabbbb 
2 length: 115 
1: abbabaabbbbbbbbbababbbbbabbbabbbabaaabbbbbbbabababbbbbbbbbabbbbbbbababababbabbbbaabbbaaabbabaaababaaaabaabbaabbbb 
1 length: 115 

$ java ThreadTester 
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException 
    at java.lang.System.arraycopy(Native Method) 
    at java.lang.String.getChars(String.java:862) 
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:408) 
    at java.lang.StringBuilder.append(StringBuilder.java:136) 
    at StringContainer.addToSb(StringContainer.java:14) 
    at ThreadTester.main(ThreadTester.java:14) 
2: abbbbbbababbbbabbbbababbbbaabbabbbaaabbbababbbbabaabaabaabaaabababaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 
2 length: 114 

ग्रहण से चलते समय ArrayIndexOutOfBoundsException भी हो रहा है।

अद्यतन 2: दो समस्याएं हो रही हैं। स्ट्रिंगबिल्डर की सामग्री की पहली समस्या लंबाई से मेल नहीं खाती है केवल ग्रहण में हो रही है और जब मैं कमांड लाइन में नहीं चलाता (कम से कम 100+ बार मैंने इसे कमांड लाइन पर चलाया तो यह कभी नहीं हुआ)।

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

बीटीडब्ल्यू, मैं @ ग्रेबेर्डेडजीक के उत्तर से सहमत हूं कि यह पूरा अभ्यास समय की एक बड़ी बर्बादी है :-)। कभी-कभी हमें केवल कुछ लक्षणों को देखने के लिए लक्षण मिलते हैं और आश्चर्य होता है कि क्या गलत हो रहा है।यह सवाल घोषित एक प्रायोरी कि दो धागे एक (बहुत अच्छी तरह से जाना जाता है) धागा असुरक्षित वस्तु संशोधित कर रहे हैं।

अद्यतन 3: यहां Java Concurrency in Practice पी का आधिकारिक उत्तर दिया गया है। 35:

  • तुल्यकालन, संकलक, प्रोसेसर और क्रम के अभाव जिस क्रम में आपरेशन निष्पादित करने के लिए प्रकट करने के लिए कुछ पूरी तरह अजीब बातें करते हैं सकते हैं। प्रयास में जिस क्रम स्मृति कार्यों अपर्याप्त सिंक्रनाइज़ बहु कार्यक्रमों में भी हो "चाहिए" लगभग निश्चित रूप से गलत होगा के बारे में तर्क करने की।

  • अपर्याप्त रूप से सिंक्रनाइज़ समवर्ती कार्यक्रमों के बारे में तर्क निषिद्ध रूप से कठिन है।

पी पर पुस्तक में NoVisibility का एक अच्छा उदाहरण भी है। 34.

+0

कि अजीब बात है, मेरे मशीन पर इसे बाहर प्रिंट '199' और' 200' और 'StringBuilder' के आकार वर्ण की संख्या के रूप में ही है। मैंने यह कई बार भाग लिया है लेकिन प्रत्येक बार एक ही परिणाम प्राप्त करने के लिए –

+0

यह भी आईडीई के साथ कुछ करने के लिए है। प्रारंभ में मैंने इंटेलिजे का इस्तेमाल किया और यह हमेशा '199' और' 200' की लंबाई देता था। इसके बाद मैंने इसे ब्लूजे में चलाया और यह हर रन पर परिवर्तनीय लंबाई प्रदान करता है। ऐसा लगता है कि इंटेलिजे अन्य आईडीई की तुलना में एकाधिक धागे को संभालने में बेहतर है। –

+0

कमांड लाइन आईडीई से परिणाम प्राप्त करने का कोई मौका? :) –

उत्तर

7

एक गैर threadsafe वर्ग जब एक से अधिक थ्रेड द्वारा समवर्ती पहुँचा के व्यवहार "अनिर्धारित" परिभाषा से है।

ऐसे मामले में निर्धारक व्यवहार का पता लगाने का कोई भी प्रयास है, आईएमएचओ, बस समय की एक बड़ी बर्बादी है।

+3

फिर भी मुझे लगता है कि मुद्रित लंबाई 137 के साथ यह मामला और वास्तविक लंबाई 50 भी "अपरिभाषित" व्यवहार के साथ असंभव है। –

0

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

पहले और दूसरे println अन्य धागा बीच एक अतिरिक्त पाश पूरा किया और बफर की सामग्री को बदल दिया है।

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