2015-05-27 4 views
12

मेरे कोड:क्या स्ट्रिंगबिल्डर थ्रेडसेफ है (समानांतर स्ट्रीम के साथ इसका उपयोग कर रहा है)?

StringBuilder sb = new StringBuilder(); 

events.parallelStream().forEach(event -> { 
    sb.append(event.toString()); 
    sb.append("\n"); 
}); 

मैं अंतिम परिणाम में events.toString() के आदेश के बारे में परवाह नहीं है। लेकिन मुझे परवाह है कि events.toString() निश्चित रूप से मिश्रित/गड़बड़ किए बिना, एक के बाद एक पंक्ति को सही ढंग से दिखाई देगा।

parallelStream (stream के बजाय) इस संबंध में सुरक्षित है?

+1

भले ही आपने स्ट्रिंगबफर का उपयोग किया हो, फिर भी आपको एक पंक्ति में दो घटनाएं मिल सकती हैं और फिर पंक्ति में दो नई पंक्तियां मिल सकती हैं। – Random832

+0

उत्तर नहीं है। (उपयोगी हो सकता है: [मैं प्रोग्रामेटिक रूप से कैसे साबित करूं कि स्ट्रिंगबिल्डर थ्रेडसेफ नहीं है?] (https://stackoverflow.com/questions/48558432)) – Andrew

उत्तर

17

बेहतर समाधान

events.parallelStream().map(event -> event+"\n").collect(Collectors.joining()); 

या वैकल्पिक रूप से (@Holger करने के लिए धन्यवाद) का प्रयोग है। आम तौर पर collect या reduce जैसे कमी संचालन बेहतर विकल्प होते हैं।

+0

समानांतर धाराओं के सभी कार्यों के बीच या इसके बीच में तारों का संग्रह होता है? क्योंकि मुझे लगता है कि 'समानांतरस्ट्रीम' का उपयोग दृश्यों के पीछे ढांचे में शामिल हो जाता है। –

+0

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

+6

अभी भी बेहतर: 'events.parallelStream() नक्शा (ऑब्जेक्ट :: toString) .collect (collect.joining ("\ n", "", "\ n")); ' – Holger

4

नहीं, ऐसा नहीं है। जैसा कि its javadoc में उल्लेख किया गया है:

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

इसके बजाय StringBuffer का उपयोग करें।

events.parallelStream().map(Object::toString).collect(Collectors.joining("\n", "", "\n")); 

सामान्य से बचने धाराओं के लिए forEach के रूप में टर्मिनल आपरेशन का उपयोग कर में:

+2

ध्यान दें कि यदि आप 'स्ट्रिंगबफर' का उपयोग करते हैं तो आपको समांतरता से लाभ होने की संभावना नहीं होगी मामला। मुझे पूरा यकीन है कि यह अनुक्रमिक धारा से भी धीमा होगा क्योंकि असल में कुछ भी नहीं किया जाएगा; एक को छोड़कर सभी धागे सिर्फ मॉनीटर पर इंतजार करेंगे। –

+0

@TagirValeev यह सच नहीं है। ईवेंट 'toString विधियों को समानांतर में निष्पादित किया जाएगा। – Random832

8

नहीं, यह थ्रेड-सुरक्षित नहीं है।

पुराने StringBuffer और नए StringBuilder के बीच यह मुख्य अंतर है - पूर्व की विधियां सिंक्रनाइज़ होती हैं, जबकि उत्तरार्द्ध नहीं होते हैं।

इसके बजाय ऐसा करने में बहुत उपयोगी नहीं है, भले ही आप StringBuffer का उपयोग करें - थ्रेड को StringBuffer पर लिखने के लिए एक-दूसरे पर इंतजार करना होगा।

+4

और भूलना न भूलें, यहां तक ​​कि 'स्ट्रिंगबफर' का उपयोग करते समय, लैम्ब्डा अभिव्यक्ति के भीतर किए गए दो 'एपेंड' कॉल मनमाने ढंग से अंतःस्थापित हो सकते हैं जब लैम्ब्डा अभिव्यक्ति को अतिरिक्त सिंक्रनाइज़ेशन के बिना समवर्ती रूप से निष्पादित किया जाता है। – Holger

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