2013-01-11 31 views
7

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

मेरे पास एक ऐसा एप्लिकेशन है जो रीयलटाइम या गैर-रीयलटाइम मोड में काम कर सकता है। मामले में यह वास्तविक समय है, मैं बस निम्नलिखित उपयोग कर रहा हूँ:

THREAD_POOL = Executors.newCachedThreadPool(); 

लेकिन मामले में यह वास्तविक समय नहीं है, मैं अपने थ्रेड पूल के आकार नियंत्रित करने की क्षमता चाहते हैं। ऐसा करने के लिए, मैं 2 विकल्पों के बारे में सोच रहा हूं, लेकिन मैं वास्तव में अंतर को समझ नहीं पा रहा हूं, और कौन सा बेहतर प्रदर्शन करेगा।

THREAD_POOL = Executors.newFixedThreadPool(threadPoolSize); 

विकल्प 2 मेरे अपने ThreadPoolExecutor इस तरह बनाने के लिए है:

विकल्प 1 आसान तरीका उपयोग करने के लिए है

RejectedExecutionHandler rejectHandler = new RejectedExecutionHandler() { 
@Override 
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { 
    try { 
     executor.getQueue().put(r); 
    } catch (Exception e) {} 
} 
};   
THREAD_POOL = new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(10000), rejectHandler); 

मैं समझने के लिए उपयोग करने का लाभ है चाहते हैं अधिक जटिल विकल्प 2, और अगर मुझे LinkedBlockingQueue से अधिक डेटा संरचना का उपयोग करना चाहिए? किसी भी सहायता की सराहना की जाएगी।

उत्तर

13

स्रोत कोड को देखते हुए आपको लगता है कि एहसास होगा:

Executors.newFixedThreadPool(threadPoolSize); 

को बराबर है:

return new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0L, MILLISECONDS, 
           new LinkedBlockingQueue<Runnable>()); 

चूंकि यह प्रदान नहीं करता है स्पष्ट RejectedExecutionHandler, डिफ़ॉल्ट AbortPolicy प्रयोग किया जाता है। एक बार कतार भरने के बाद यह मूल रूप से RejectedExecutionException फेंकता है। लेकिन कतार असंबद्ध है, इसलिए यह कभी पूरा नहीं होगा। इस प्रकार यह निष्पादक कार्यों की संख्या को स्वीकार करता है।

आपका घोषणा और अधिक जटिल और काफी अलग है:

  • new LinkedBlockingQueue<Runnable>(10000) थ्रेड पूल कार्य निरस्त करने के लिए करता है, तो 10000 से अधिक इंतजार कर रहे हैं का कारण होगा।

  • मुझे नहीं पता कि आपका RejectedExecutionHandler क्या कर रहा है। यदि पूल पता चलता है कि यह कतार में और अधिक रननेबल नहीं रख सकता है तो यह आपके हैंडलर को कॉल करता है। इस हैंडलर में आप ... Runnable को फिर से कतार में डालने का प्रयास करें (जो ब्लॉक के 99% मामलों में विफल हो जाएगा)। अंत में आप अपवाद निगलते हैं। ऐसा लगता है कि ThreadPoolExecutor.DiscardPolicy वह है जो आप के बाद हैं।

    नीचे दी गई टिप्पणियों को देखते हुए ऐसा लगता है कि यदि आप कार्य कतार बहुत बड़ी हैं तो आप ब्लॉक करने की कोशिश कर रहे हैं या किसी भी तरह से थ्रॉटल क्लाइंट हैं। मुझे नहीं लगता कि RejectedExecutionHandler के अंदर अवरुद्ध करना एक अच्छा विचार है। इसके बजाय CallerRunsPolicy अस्वीकृति नीति पर विचार करें। पूरी तरह से एक ही नहीं, लेकिन पर्याप्त करीब है।

लपेटने के लिए: यदि आप लंबित कार्यों की संख्या सीमित करना चाहते हैं, तो आपका दृष्टिकोण लगभग अच्छा है। यदि आप समवर्ती धागे की संख्या को सीमित करना चाहते हैं, तो पहला एक-लाइनर पर्याप्त है।

1 - यह सोचते हैं 2^31 अनंत

+0

है 'RejectedExecutionHandler' वास्तव में ब्लॉक कर रहा है,' executor.getQueue() करने के लिए कॉल डाल (आर), 'जब तक कतार मिल जाता है को अवरुद्ध कर देगा, इसलिए। अंत में मेरे हैंडलर किसी भी कार्य को निरस्त किए बिना एक बाध्य कतार रखने की अनुमति देता है। जब तक मैं गलत नहीं हूँ। अन्य विवरण के लिए +1। –

+0

@CharlesMenguy: स्पष्टीकरण के लिए धन्यवाद, मेरा बुरा, मैं अपना प्रश्न अपडेट करूंगा। लेकिन आप 'अस्वीकृत निष्पादन हैंडलर' के अंदर अवरुद्ध करके क्या हासिल करना चाहते हैं? मेरा मानना ​​है कि इसमें कुछ वास्तव में अप्रत्याशित दुष्प्रभाव हो सकते हैं जैसे कॉलर थ्रेड को अवरुद्ध करना। शायद आपको 'कॉलररंस पॉलिसी' की आवश्यकता है? –

+0

असल में इसे देखने के बाद, 'कॉलररंस पॉलिसी' वास्तव में जो मैं करना चाहता हूं उसके लिए वादा करता हूं, मैं इसे धन्यवाद देने का प्रयास करूंगा! शायद आप इसे उत्तर में जोड़ सकते हैं और मैं आपका जवाब स्वीकार करूंगा। –