2013-03-18 5 views
16

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

private final ExecutorService s3UploadPool = 
new ThreadPoolExecutor(1, 40, 1, TimeUnit.HOURS, unboundedLoggingQueue); 

यह नए धागे क्यों नहीं बना रहा है?

+0

http://stackoverflow.com/questions/19528304/how-to-get-the-threadpoolexecutor-to-increase-threads-to-max-before-queueing/19528305#19528305 – Gray

उत्तर

16

यह पकड़ लिया this blog post में शामिल है:

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

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

public static ExecutorService newScalingThreadPool(int min, int max, long keepAliveTime) { 
    ScalingQueue queue = new ScalingQueue(); 
    ThreadPoolExecutor executor = 
     new ScalingThreadPoolExecutor(min, max, keepAliveTime, TimeUnit.MILLISECONDS, queue); 
    executor.setRejectedExecutionHandler(new ForceQueuePolicy()); 
    queue.setThreadPoolExecutor(executor); 
    return executor; 
} 

हालांकि अधिक बस maxPoolSize करने के लिए corePoolSize की स्थापना की और इस बकवास के बारे में चिंता मत करो।

+0

नोट से संबंधित, आप अभी भी देख सकते हैं कोर थ्रेड को टाइमआउट पर अनुमति देकर सीमित स्केलिंग प्रभाव प्राप्त करें (आप 0 से अधिकतम धागे तक स्केल कर सकते हैं)। – jtahlborn

+0

javadocs के अनुसार: corePoolSize और maxPoolSize को सेट करके, आप एक निश्चित आकार का थ्रेड पूल बनाते हैं। तो यदि आप अपनी आखिरी वाक्य का पालन करते हैं तो आप केवल एक्जिक्यूटर्स.न्यूफिक्स्ड थ्रेडपूल (पूलसाइज) का उपयोग करके बेहतर होंगे। – darrickc

+0

@darrickc ऐसा लगता है कि आपका संपादन पहले ही अस्वीकार कर दिया गया था लेकिन टिप्पणी में शामिल करना उचित होगा। मुझे नहीं लगता कि यह मान्य है क्योंकि मेरे उपयोग के मामलों में मैं धागे को समय-समय पर नहीं चाहता हूं। – djechlin

3

जैसा कि @ डीजेक्लिन द्वारा उल्लिखित है, यह ThreadPoolExecutor के परिभाषित व्यवहार (कई आश्चर्यजनक) का हिस्सा है। मेरा मानना ​​है कि मैं इस व्यवहार के कुछ हद तक एक सुरुचिपूर्ण समाधान है कि मैं अपने जवाब यहाँ दिखा पाया है:

How to get the ThreadPoolExecutor to increase threads to max before queueing?

मूल रूप से आप का विस्तार LinkedBlockingQueue यह हमेशा queue.offer(...) के लिए रिटर्न फाल्स जो एक जोड़ देगा के लिए यदि आवश्यक हो तो पूल के लिए अतिरिक्त धागे। यदि पूल पहले से ही अधिकतम धागे पर है और वे सभी व्यस्त हैं, RejectedExecutionHandler कहा जाएगा। यह हैंडलर है जो कतार में put(...) करता है।

मेरा कोड वहां देखें।

+1

धन्यवाद। फिक्स्ड। @kevinarpe। – Gray

3

इस समस्या का समाधान है। निम्नलिखित कार्यान्वयन पर विचार करें:

int corePoolSize = 40; 
int maximumPoolSize = 40; 
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 
    60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); 
threadPoolExecutor.allowCoreThreadTimeOut(true); 

true को allowCoreThreadTimeOut() की स्थापना करके, पूल में धागे निर्दिष्ट समय (इस उदाहरण में 60 सेकंड) के बाद समाप्त करने के लिए अनुमति दी जाती है। इस समाधान के साथ, यह corePoolSize कन्स्ट्रक्टर तर्क है जो अभ्यास में अधिकतम पूल आकार निर्धारित करता है, क्योंकि थ्रेड पूल corePoolSize तक बढ़ जाएगा, और फिर कतार में नौकरियां जोड़ना शुरू करें। यह संभावना है कि पूल कभी भी इससे बड़ा नहीं हो सकता है, क्योंकि पूल कतार पूर्ण होने तक नए धागे नहीं उगाएगा (जो कि LinkedBlockingQueue में Integer.MAX_VALUE क्षमता कभी नहीं हो सकती है)।नतीजतन, maximumPoolSize को corePoolSize से बड़े मान पर सेट करने में बहुत कम बिंदु है।

विचार: थ्रेड पूल में समय समाप्ति के बाद 0 निष्क्रिय धागे हैं, जिसका अर्थ है कि थ्रेड बनने से पहले कुछ विलंबता होगी (आमतौर पर, आपके पास हमेशा corePoolSize धागे उपलब्ध होंगे)।

अधिक जानकारी ThreadPoolExecutor के जावाडॉक में अधिक जानकारी मिल सकती है।

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