112

newCachedThreadPool() बनाम newFixedThreadPool()Executors.newCachedThreadPool() Executors.newFixedThreadPool बनाम()

जब मैं एक या अन्य इस्तेमाल करना चाहिए? संसाधन उपयोग के संदर्भ में कौन सी रणनीति बेहतर है?

+0

मैं है ... fixedThreadPool @ 3 धागे स्मृति त्रुटि के बाहर खड़ी कर रहा है हाँ मैं docs..the समस्या माध्यम से चले गए मान लें कि आपके जावा के बारे में बात कर रहे हैं? – Mark

+0

हाँ मार्क मैं :) हूँ! – hakish

उत्तर

141

मुझे लगता है कि डॉक्स अंतर और उपयोग इन दोनों कार्यों की बहुत अच्छी तरह से व्याख्या करते हैं:

newFixedThreadPool

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

newCachedThreadPool

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

संसाधनों के संदर्भ में, newFixedThreadPool सभी धागे तब तक चलेंगे जब तक उन्हें स्पष्ट रूप से समाप्त नहीं किया जाता है। newCachedThreadPool थ्रेड जो साठ सेकंड के लिए उपयोग नहीं किए गए हैं उन्हें कैश से हटा दिया गया है और हटा दिया गया है।

यह देखते हुए, संसाधन खपत स्थिति में बहुत अधिक निर्भर करेगा। उदाहरण के लिए, यदि आपके पास लंबे समय तक चलने वाले कार्यों की एक बड़ी संख्या है तो मैं FixedThreadPool का सुझाव दूंगा। CachedThreadPool के लिए, दस्तावेज़ कहते हैं कि "ये पूल आमतौर पर उन कार्यक्रमों के प्रदर्शन में सुधार करेंगे जो कई अल्पकालिक असीमित कार्यों को निष्पादित करते हैं"।

+1

.. जहां कैशपूल आंतरिक रूप से केवल एक धागा बना रहा है .. ढेर आकार में वृद्धि करने के लिए मुझे दोनों के लिए एक ही प्रदर्शन मिल रहा है..इसके पास कुछ और है जो मुझे याद आ रही है !! – hakish

+1

क्या आप थ्रेडपूल को कोई थ्रेडफैक्टरी प्रदान कर रहे हैं? अनुमान है कि धागे में कुछ राज्य भंडारित हो सकता है जो कचरा नहीं जा रहा है। यदि नहीं, तो शायद आपका प्रोग्राम ढेर सीमा के आकार के करीब इतना चल रहा है कि 3 धागे के निर्माण के साथ यह आउटऑफमेमरी का कारण बनता है।इसके अलावा, यदि कैशपूल आंतरिक रूप से केवल एक धागा बना रहा है तो यह संभवतः इंगित करता है कि आपके कार्य सिंक्रनाइज़ किए जा रहे हैं। –

3

आप newCachedThreadPool का उपयोग करना चाहिए आप अल्पकालिक अतुल्यकालिक कार्य के रूप में, जावाडोक में कहा गया है अगर आप कार्यों के लिए जो प्रक्रिया में अधिक समय समय लगता है प्रस्तुत है केवल जब, आप बहुत अधिक धागे बनाने खत्म हो जाएगा।यदि आप तेजी से चल रहे कार्यों को नए कैश किए गए थ्रेडपूल (http://rashcoder.com/be-careful-while-using-executors-newcachedthreadpool/) पर लंबे समय तक चलने वाले कार्यों को सबमिट करते हैं तो आप 100% CPU दबा सकते हैं।

7

यह सही है, Executors.newCachedThreadPool() सर्वर कोड के लिए एक अच्छा विकल्प नहीं है जो एकाधिक ग्राहकों और समवर्ती अनुरोधों की सेवा कर रहा है।

क्यों? वहाँ मूलतः दो (संबंधित) इसके साथ समस्याएं हैं:

  1. यह जिसका मतलब है कि आप बस सेवा (DOS का दौरा) में अधिक काम इंजेक्शन लगाने के द्वारा अपने JVM को बिगाड़ रहा किसी के लिए दरवाजा खोल रहे हैं, असीम है। धागे एक गैर-नगण्य मात्रा की स्मृति का उपभोग करते हैं और उनकी कार्य-प्रगति के आधार पर स्मृति खपत भी बढ़ाते हैं, इसलिए सर्वर को इस तरह से अपनाना काफी आसान है (जब तक आपके पास अन्य सर्किट ब्रेकर नहीं होते)।

  2. असंबद्ध समस्या इस तथ्य से उत्साहित है कि निष्पादक को SynchronousQueue द्वारा सामने रखा गया है जिसका अर्थ है कि कार्यकर्ता और थ्रेड पूल के बीच सीधी हैंडऑफ है। यदि सभी मौजूदा धागे व्यस्त हैं तो प्रत्येक नया कार्य एक नया धागा बनाएगा। यह आमतौर पर सर्वर कोड के लिए एक बुरी रणनीति है। जब सीपीयू संतृप्त हो जाता है, तो मौजूदा कार्यों को पूरा करने में अधिक समय लगता है। फिर भी अधिक कार्य सबमिट किए जा रहे हैं और अधिक धागे बनाए गए हैं, इसलिए कार्यों को पूरा करने में लंबा और लंबा समय लगता है। जब सीपीयू संतृप्त होता है, तो निश्चित रूप से अधिक थ्रेड निश्चित रूप से सर्वर की आवश्यकता नहीं होती है।

यहाँ मेरी सुझाव दिए गए हैं: एक निश्चित-आकार थ्रेड पूल Executors.newFixedThreadPool या धागे का एक सेट अधिकतम संख्या के साथ एक ThreadPoolExecutor.

उपयोग;

9

यदि आप grepcode में कोड देखते हैं, तो आप देखेंगे कि वे आंतरिक रूप से ThreadPoolExecutor. पर कॉल कर रहे हैं और अपनी संपत्तियां सेट कर रहे हैं। आप अपनी आवश्यकता के बेहतर नियंत्रण के लिए अपना एक बना सकते हैं।

public static ExecutorService newFixedThreadPool(int nThreads) { 
    return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS, 
new LinkedBlockingQueue<Runnable>()); 
} 

public static ExecutorService newCachedThreadPool() { 
     return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 
             60L, TimeUnit.SECONDS, 
             new SynchronousQueue<Runnable>()); 
} 
+1

बिल्कुल, एक कैश ऊपरी सीमा के साथ एक कैश किए गए थ्रेड निष्पादक और कहते हैं, निष्क्रिय अवसरों का 5-10 मिनट अधिकांश अवसरों के लिए बिल्कुल सही है। –

5

आप प्रतिदेय/Runnable कार्यों की असीम कतार के बारे में चिंतित नहीं हैं, तो आप उनमें से एक का उपयोग कर सकते हैं। जैसा कि ब्रूनो द्वारा सुझाया गया है, मैं भी इन दोनों के बीच newFixedThreadPoolnewCachedThreadPool पसंद करता हूं।

लेकिन ThreadPoolExecutor अधिक लचीला सुविधाओं दोनों newFixedThreadPool या newCachedThreadPool

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, 
TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, 
RejectedExecutionHandler handler) 

लाभ की तुलना में प्रदान करता है:

  1. आप पर BlockingQueue आकार पूरा नियंत्रण है। यह पहले दो विकल्पों में विपरीत नहीं है। सिस्टम में अप्रत्याशित अशांति में लंबित कॉल करने योग्य/चलने योग्य कार्यों के विशाल ढेर के कारण मुझे स्मृति त्रुटि से बाहर नहीं मिलेगा।

  2. आप कस्टम अस्वीकृति से निपटने नीति को लागू करने या नीतियों में से एक का उपयोग कर सकते हैं:

    1. डिफ़ॉल्ट ThreadPoolExecutor.AbortPolicy में, हैंडलर अस्वीकृति पर एक क्रम RejectedExecutionException फेंकता है।

    2. ThreadPoolExecutor.CallerRunsPolicy में, जो धागा निष्पादित करता है वह स्वयं कार्य को चलाता है। यह एक साधारण प्रतिक्रिया नियंत्रण तंत्र प्रदान करता है जो नए कार्यों को जमा करने की दर को धीमा कर देगा।

    3. ThreadPoolExecutor.DiscardPolicy में, एक कार्य जिसे निष्पादित नहीं किया जा सकता है, को छोड़ दिया जाता है।

    4. ThreadPoolExecutor.DiscardOldestPolicy में, यदि निष्पादक बंद न किया गया, काम कतार के सिर पर कार्य गिरा दिया है, और फिर पुन: प्रयास निष्पादन किया जाता है (जो फिर से असफल हो सकता है, जिससे यह दोहराया जाना।)

  3. आप उपयोगों की सूची नीचे के लिए कस्टम थ्रेड कारखाने को लागू कर सकते हैं:

    1. एक और वर्णनात्मक धागा नाम
    2. धागा डेमॉन स्थिति
    3. +०१२३५१६४१०६ सेट करने के लिए सेट करने के लिए
    4. धागा प्राथमिकता सेट करने के लिए
39

बस अन्य उत्तर पूरा करने के लिए, मैं प्रभावी जावा, 2 संस्करण, उद्धृत करने के लिए यहोशू बलोच, अध्याय 10, मद 68 से चाहते हैं:

" किसी विशेष एप्लिकेशन के लिए निष्पादक सेवा का चयन करना मुश्किल हो सकता है। यदि आप एक छोटे प्रोग्राम, या एक हल्के से भरी हुई सर्वर, Executors.new- CachedThreadPool का उपयोग कर लिख रहे हैं आम तौर पर एक अच्छा विकल्प, के रूप में यह कोई विन्यास की मांग है और आम तौर पर है "सही काम करता है।" लेकिन एक कैश्ड थ्रेड पूल भारी लोड उत्पादन सर्वर के लिए एक अच्छा विकल्प नहीं है!

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

इसलिए, एक भारी लोड उत्पादन सर्वर में , आप Executors.newFixedThreadPool, जो आप अधिकतम नियंत्रण के लिए धागे की एक निश्चित संख्या, या ThreadPoolExecutor वर्ग सीधे का उपयोग कर, के साथ एक पूल देता का उपयोग कर बंद काफी बेहतर हैं । "