2009-08-16 11 views
14

मैं java.text.NumberFormat का उपयोग केवल अधिक पठनीय स्ट्रिंग्स में संख्या परिवर्तित करने के लिए, अल्पविराम, हजारों को अलग करने के साथ आदि मूल रूप से मैं इसे के रूप में परिभाषित करते हैं:जावा: संख्याफॉर्मैट के साथ सिंक्रनाइज़ेशन समस्या?

public static NumberFormat nf = NumberFormat.getInstance(Locale.US); 

... और फिर मैं सिर्फ nf.format फोन (some_number) किसी भी धागे में जहां मैं किसी संख्या का एक पठनीय संस्करण बनाना चाहता हूं। लेकिन JavaDoc को देखते हुए, यह कहते हैं: "संख्या स्वरूपों आम तौर पर सिंक्रनाइज़ नहीं कर रहे हैं यह प्रत्येक थ्रेड के लिए अलग प्रारूप उदाहरण बना की सिफारिश की है एक से अधिक थ्रेड एक प्रारूप समवर्ती तक पहुंचते हैं तो इसे बाहर से सिंक्रनाइज़ किया जाना चाहिए।।।"

मैं केवल NumberFormat वस्तु का प्रारूप (संख्या) विधि का उपयोग कर रहा है, वहाँ कभी एक तुल्यकालन मुद्दा हो सकता है? मैंने इसके बजाय NumberFormat.getInstance (Locale.US) .format (संख्या) का उपयोग करने का प्रयास किया, लेकिन ऐसा करने के साथ ओवरहेड जुड़ा हुआ है जो हर बार मुझे लगता है कि वास्तव में इसकी आवश्यकता नहीं है। क्या इसे वास्तव में बाहरी सिंक्रनाइज़ेशन की आवश्यकता है? या क्या नंबरफॉर्मैट के बिना एक ही चीज़ को पूरा करने का एक आसान, कुशल तरीका है?

धन्यवाद!

उत्तर

15

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

हालांकि, मैं सबसे सरल तरीका है विश्वास करते हैं, तो आप प्रारूप/एक पंक्ति में कई संख्या पार्स करने के लिए जा रहे हैं विशेष रूप से अगर, मैन्युअल रूप से एक ThreadLocal उपयोग करने के लिए है।

+0

इसे https://gist.github.com/jontejj/5430320 का उपयोग करके माप लिया गया, परिणाम http://1.microbenchmarks.appspot.com/run/[email protected]/se.softhouse पर प्रकाशित किए गए हैं .common.numbers.NumberFormat लाभ प्राप्त करना वास्तव में काफी महत्वपूर्ण है अगर प्रारूपण संख्या केवल एक ही चीज चल रही है। यह संख्याफॉर्मैट बनाए गए स्वरूपकों के लिए कैश रखता है और उन्हें वापस करने से पहले केवल उन्हें क्लोन करता है। – jontejj

+0

और यह सब सबक्लास पर लागू होता है .. विशेष रूप से डेटफॉर्मैट – Snicolas

8

उपयोग एक ThreadLocal <NumberFormat>। इस तरह प्रत्येक धागे का अपना निजी नंबरफॉर्मैट उदाहरण होगा और सिंक्रनाइज़ करने की आवश्यकता नहीं होगी और केवल न्यूनतम ओवरहेड होगा।

1

वहाँ एक NumberFormat वस्तु साझा करने के लिए कोई कारण नहीं है। हां, इसमें सिंक्रनाइज़ेशन समस्याएं हो सकती हैं (अपने लोकेल के लिए स्रोत देखें और आप देखेंगे कि वे सदस्य चर का उपयोग भी प्रारूप में करते हैं)। जब तक आपके पास प्रदर्शन समस्याएं न हों (जो आप सबसे अधिक संभावना नहीं करेंगे), बस प्रत्येक उपयोग के लिए एक नया बनाएं।

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

3

NumberFormat और DecimalFormat के स्रोत कोड को देखते हुए, वहाँ मध्यवर्ती परिणाम के लिए इस्तेमाल किसी भी खेतों होने लगते हैं नहीं है - केवल समस्या यह है कि प्रारूप में ही (दशमलव अंक की जैसे संख्या) setters के माध्यम से परिवर्तनशील है तो एक धागा इसे बदल सकता है जबकि format() कॉल संसाधित किया जा रहा है, और यह निश्चित रूप से एक गड़बड़ी का कारण बन जाएगा।

यदि आप कभी भी सेटर्स का उपयोग नहीं करते हैं, तो ठीक होना चाहिए - लेकिन निश्चित रूप से यह केवल वर्तमान कार्यान्वयन है। मैं एपीआई दस्तावेज़ों के विपरीत इसके आधार पर सहज महसूस नहीं करूंगा। ThreadLocal का उपयोग करना एक अच्छा समझौता जैसा लगता है।

+1

मुझे पता है कि यह एक पुराना उत्तर है, लेकिन ... आपको वास्तव में स्रोत कोड से नहीं जाना चाहिए। यहां तक ​​कि यदि आप जानते हैं कि जावा का कौन सा संस्करण आप उपयोग कर रहे हैं, तो यह विक्रेताओं के बीच अलग है। (उदाहरण के लिए, मैंने आईबीएम और सन/ओरेकल जेवीएम के बीच बहुत सारे अंतर देखे हैं।) –

+0

जेडीके के मेरे संस्करण में वास्तव में मध्यवर्ती परिणाम संग्रहीत होते हैं, लेकिन जैसा कि आपने वाईएमएमवी कहा था। – jontejj

2

NumberFormat एक abstract class है। getInstance पर कॉल करते समय इसका डिफ़ॉल्ट DecimalFormat का उदाहरण वापस करना है।DecimalFormat अपनी स्वरूपण प्रक्रिया, उपसर्ग और प्रत्यय के लिए पैटर्न, boolean एस के संदर्भ में अपनी स्थिति को बनाए रखने के लिए फ़ील्ड का एक समूह का उपयोग करता है, यह दर्शाता है कि घातीय नोटेशन और हजारों समूह, int एस का पूर्णांक और अंश भागों आदि के आकार का वर्णन करने के लिए या नहीं।

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

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