2012-12-20 9 views
6

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

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

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

अब, मुझे लगता है कि मुझे संदेश लेना चाहिए, उन्हें "कैश" (एक स्ट्रिंग सरणी की तरह) में स्टोर करना चाहिए, फिर "कैश" भरने पर स्ट्रिंग सरणी को फ़ाइल में सहेजें। क्या यह बेहतर अभ्यास है?

तो मैं दो प्रश्न हैं:

1) यदि आप फ़ाइल का उपयोग नहीं कर रहे हैं एक फ़ाइल खुला समय की एक विस्तारित अवधि के लिए (कुछ ही घंटों के लिए कुछ मिनट) छोड़ने के लिए अच्छा अभ्यास है?

2) "कैश" के लिए अच्छा अभ्यास क्या है जैसे मैं बात कर रहा हूं? एक स्ट्रिंग सरणी अच्छा है? क्या मुझे कुछ बेहतर उपयोग करना चाहिए? आप इस जानकारी को संग्रहीत करने के बारे में कैसे जाएंगे?

उत्तर

3

मेरी राय में, सर्वर अनुप्रयोगों में लॉग (और इसी तरह) के लिए सर्वोत्तम अभ्यास एक स्वीकार्य समय देरी का निर्णय लेना और इसके साथ चिपकना है। उदाहरण के लिए, यदि आप 5 सेकंड देरी सेट करते हैं, तो कोड लिखें ताकि:

  • यदि आप लॉग में कुछ लिखते हैं, तो यह वास्तव में 5 सेकंड के भीतर लिखा जाएगा।
  • यदि कुछ और 5 सेकंड से पहले लिखा जाता है, तो यह केवल बफर में जोड़ा जाता है (समय समाप्त होने पर लिखा जाना चाहिए)।

इस तरह, आप केवल 5 सेकंड प्रति अधिकतम डिस्क लिखते हैं, लेकिन यह निश्चित रूप से लिखा जाता है। यह अन्य तरीकों के लिए अच्छी तरह से तुलना:

  • डिस्क के लिए आप फ्लश डेटा को हर बार कुछ भी लिखा जाता है, लेकिन लोड बढ़ जाती है और वहाँ हैं, कहते हैं, प्रति सेकंड 10,000 घटनाओं, तो आप आई/ओ समय बर्बाद कर दिया जाएगा प्रति सेकंड 10,000 डिस्क लिखते हैं।
  • यदि आप इसे डेटा फ्लश करने का निर्णय लेने के लिए जावा/ओएस पर छोड़ देते हैं, लेकिन लोड बहुत कम है (उदा। रात के मध्य में), लॉग भी समय से बाहर हो सकता है। (यदि एक घटना है, तो बफर भरने के लिए पर्याप्त नहीं है, तो घंटों के लिए कुछ भी नहीं।)

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

फ़ाइल खोलने के बारे में, आप जितनी देर चाहें खुली फाइलें छोड़ सकते हैं (बस इसे बंद करें जब आप इसे और लिखने वाले नहीं हैं)। मान लीजिए कि आपके पास हजारों फाइलें खुली नहीं हैं, और आपको एक ही फ़ाइल में एकाधिक एप्लिकेशन लिखने की आवश्यकता नहीं है, इससे कोई समस्या नहीं आती है।

+0

> सर्वर अनुप्रयोगों में लॉग (और इसी तरह) के लिए सर्वोत्तम अभ्यास स्वीकार्य समय देरी का निर्णय लेना और इसके साथ चिपकना है। क्या आप इसे कैसे कर सकते हैं इस बारे में विस्तार से बता सकते हैं? या मुझे यह जानने के लिए दिशा में इंगित करें कि यह कैसे करें? इसके अलावा, BuffereOutputStream का उपयोग करने के तरीके के बारे में कुछ और जानकारी अच्छी होगी। मैं इसे सही तरीके से उपयोग करने की कोशिश कर रहा हूं। क्या अन्य कक्षाएं शामिल होनी चाहिए? फ्लश() विधि का उपयोग करने के बारे में मैं कैसे सीखूं। यह भी एक अच्छा जवाब था धन्यवाद। – Bnannerz

+1

BufferedOutputStream बहुत आसान है; जैसे कि आपके पास FileOutputStream बुलाया गया है, बस नया BufferedOutputStream (आउट) करें और इसका उपयोग करें जैसे आप FileOutputStream करेंगे। यदि आप लेखकों का उपयोग कर रहे हैं, तो एक BufferedWriter है। दूसरा पैरामीटर बफर बनाने के लिए कितना बड़ा है; डिफ़ॉल्ट काफी छोटा है लेकिन जहां तक ​​मुझे पता है कि आप इसे 8 केबी या 64 केबी या जो कुछ भी पसंद कर सकते हैं। – sam

+1

समय की बात कैसे करें - यह काफी सरल है लेकिन इसमें समवर्तीता शामिल है, इसलिए आपको स्थानों में सिंक्रनाइज़ किए गए कीवर्ड का उपयोग करना होगा! असल में, अपने 'फ़ाइल में लिखें' फ़ंक्शन है ताकि यह buffered आउटपुट स्ट्रीम को लिख सके। जांचें कि क्या आपके पास पहले से लंबित 'फ्लश' टाइमर है या नहीं। यदि कोई है, तो कुछ भी नहीं; यदि नहीं, तो एक नया धागा शुरू करें जो सिर्फ 5 सेकंड (या जो कुछ भी) के लिए सोता है, फिर स्ट्रीम पर फ्लश कॉल करता है। (कॉलिंग फ्लश() बफर को साफ़ कर देगा और वास्तव में इसे डिस्क पर लिख देगा।) – sam

1

1) क्या आप फाइल का उपयोग नहीं कर रहे हैं, तो एक विस्तारित अवधि (कुछ मिनटों में कुछ मिनट) के लिए एक फ़ाइल खोलने के लिए अच्छा अभ्यास है?

मुझे लगता है कि यह इस बात पर निर्भर करता है कि आपके कार्यक्रम और प्रत्येक संदेश आकार में कितने संदेश आते हैं। अगर आपकी याददाश्त आपकी गणना से संतुष्ट हो सकती है तो आप इसके बारे में सोच सकते हैं। लेकिन जब मैं प्रत्येक संदेश आऊंगा (एक ब्लॉब हो सकता है) डेटाबेस पर लिखने के लिए मुझे लगता है। यह भी सोचें कि फ़ाइल में लिखते समय आपका प्रोग्राम क्रैश होने पर क्या हुआ। आप स्मृति पर संग्रहीत पूरे संदेश खो सकते हैं।

2) "कैश" के लिए अच्छा अभ्यास क्या है जैसे मैं बात कर रहा हूं? एक स्ट्रिंग सरणी अच्छा है? क्या मुझे कुछ बेहतर उपयोग करना चाहिए? आप इस जानकारी को संग्रहीत करने के बारे में कैसे जाएंगे?

यदि आप आकार को जानते हैं तो आप स्मृति सरणी में अस्थायी रूप से संग्रहीत डेटा ठीक है। अन्यथा आप ArrayList का उपयोग कर सकते हैं।

3

लंबे समय तक फ़ाइल खोलने के लिए बिल्कुल ठीक है। बार-बार इसे खोलने और बंद करने से यह निश्चित रूप से बेहतर है। एक खुली फ़ाइल द्वारा खपत संसाधन की मात्रा नगण्य है; आपकी एकमात्र चिंता होगी यदि आपके पास खुली फाइलें (सैकड़ों या हजारों) थीं। मैं सुझाव दूंगा कि जब आपका प्रोग्राम शुरू होता है तो फ़ाइल खोलें, और इसे समाप्त होने पर बंद करें।

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

अब, आपको इस समय के दौरान स्ट्रीम (या लेखक, या RandomAccessFile, या जो भी आप उपयोग करते हैं) flush की आवश्यकता होगी।आपको यह भी करना चाहिए जब भी आपको यह सुनिश्चित करने की आवश्यकता हो कि उस बिंदु तक लिखे गए सभी डेटा को डिस्क पर सुरक्षित रूप से लिखा गया हो; जो कि प्रत्येक संदेश के बाद हो सकता है, या किसी दिए गए संदेश के बाद, डेटा की मात्रा, या समय की अवधि के बाद, जैसा कि आप फिट देखते हैं।