2012-06-28 11 views
11

बनाने के लिए मुझे जावा (java.util.concurrent) में थ्रेड पूल को कार्यान्वित करने की आवश्यकता है, जिनकी संख्या कमजोर होने पर धागे की संख्या कम होती है, लेकिन ऊपरी बाउंड तक बढ़ती है (लेकिन कभी नहीं आगे) जब नौकरियों को निष्पादित करने की तुलना में तेज़ी से जमा किया जाता है, और जब सभी नौकरियां पूरी की जाती हैं तो निचली सीमा तक वापस आती है और कोई और नौकरियां जमा नहीं की जाती हैं।गतिशील (बढ़ते/घटते) थ्रेड पूल

आप इस तरह कुछ कैसे लागू करेंगे? मुझे कल्पना है कि यह काफी आम उपयोग परिदृश्य होगा, लेकिन स्पष्ट रूप से java.util.concurrent.Executors फैक्ट्री विधियां केवल निश्चित आकार के पूल और पूल बना सकती हैं जो कई नौकरियां जमा होने पर असंबद्ध रूप से बढ़ती हैं। ThreadPoolExecutor कक्षा corePoolSize और maximumPoolSize पैरामीटर प्रदान करती है, लेकिन इसके प्रलेखन का अर्थ यह है कि एक ही समय में corePoolSize धागे से अधिक होने का एकमात्र तरीका एक बाध्य नौकरी कतार का उपयोग करना है, इस मामले में, यदि आप maximumPoolSize धागे तक पहुंच गए हैं, आपको नौकरी के रिजेक्शन मिलेगा जिन्हें आपको अपने साथ सौदा करना है? मैं इसके साथ आया:

//pool creation 
ExecutorService pool = new ThreadPoolExecutor(minSize, maxSize, 500, TimeUnit.MILLISECONDS, 
    new ArrayBlockingQueue<Runnable>(minSize)); 
... 

//submitting jobs 
for (Runnable job : ...) { 
    while (true) { 
     try { 
      pool.submit(job); 
      System.out.println("Job " + job + ": submitted"); 
      break; 
     } catch (RejectedExecutionException e) { 
      // maxSize jobs executing concurrently atm.; re-submit new job after short wait 
      System.out.println("Job " + job + ": rejected..."); 
      try { 
       Thread.sleep(300); 
      } catch (InterruptedException e1) { 
      } 
     } 
    } 
} 

क्या मैं कुछ दिख रहा हूं? क्या ऐसा करने के लिए इससे अच्छा तरीका है? इसके अलावा, किसी की आवश्यकताओं के आधार पर, यह समस्याग्रस्त हो सकता है कि उपर्युक्त कोड कम से कम समाप्त नहीं होगा (मुझे लगता है) (total number of jobs) - maxSize नौकरियां समाप्त हो गई हैं। तो यदि आप पूल में मनमाने ढंग से नौकरियों को जमा करने में सक्षम होना चाहते हैं और उनमें से किसी के लिए इंतजार किए बिना तुरंत आगे बढ़ना चाहते हैं, तो मैं नहीं देखता कि आप समर्पित "नौकरी जमा करने" धागे के बिना ऐसा कैसे कर सकते हैं सभी जमा नौकरियों को रखने के लिए आवश्यक असंबद्ध कतार। AFAICS, यदि आप ThreadPoolExecutor के लिए एक असंबद्ध कतार का उपयोग कर रहे हैं, तो इसकी थ्रेड गिनती कोरपूलसाइज से आगे नहीं बढ़ेगी।

+3

मुझे स्वीकार करना है, मैं एक गतिशील आकार के थ्रेडपूल की उपयोगिता को देखने में विफल रहता हूं। क्या आपके बोर्ड के प्रोसेसर आपके बोर्ड के अपटाइम के दौरान बदलते हैं? – corsiKa

+3

आपकी स्थिति के लिए 'newCachedTreadPool' उपयुक्त क्यों नहीं है? यह स्वचालित रूप से उन धागे को मार देता है जिनका उपयोग अब नहीं किया जाता है। – Tudor

+0

यदि आपके निष्क्रिय धागे मर नहीं गए तो क्या होगा? मान लें कि आपके पास अधिकतम आकार का एक निश्चित आकार पूल था? क्या हुआ होगा? –

उत्तर

4

एक चाल जो आपकी मदद कर सकती है वह RejectedExecutionHandler असाइन करना है जो ब्लॉकिंग कतार में नौकरी जमा करने के लिए एक ही थ्रेड का उपयोग करती है। इससे वर्तमान धागे को अवरुद्ध कर दिया जाएगा और कुछ प्रकार के लूप की आवश्यकता को हटा दिया जाएगा।

How can I make ThreadPoolExecutor command wait if there's too much data it needs to work on?

यहाँ अस्वीकृति हैंडलर है कि इसका जवाब से नकल है:

मेरा उत्तर यहाँ देखें।

final BlockingQueue queue = new ArrayBlockingQueue<Runnable>(200); 
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(nThreads, nThreads, 
     0L, TimeUnit.MILLISECONDS, queue); 
// by default (unfortunately) the ThreadPoolExecutor will call the rejected 
// handler when you submit the 201st job, to have it block you do: 
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandler() { 
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { 
     // this will block if the queue is full 
     executor.getQueue().put(r); 
    } 
}); 

फिर आप कोर/अधिकतम धागा का उपयोग करने के रूप में लंबे समय के रूप में आप महसूस करते हैं कि घिरा अवरुद्ध कतार है कि आप पहले का उपयोग भरता से पहले किसी भी धागे कोर धागे ऊपर बनाई गई हैं गिनती सक्षम होना चाहिए। तो यदि आपके पास 10 कोर धागे हैं और आप 11 वें नौकरी को 11 वें धागे को शुरू करना चाहते हैं तो आपको 0 के आकार के साथ अवरुद्ध कतार की आवश्यकता होगी (शायद SynchronousQueue)। मुझे लगता है कि यह अन्यथा महान ExecutorService कक्षाओं में वास्तविक सीमा है।

1

maximumPoolSize से Integer.MAX_VALUE पर सेट करें। यदि आपके पास कभी 2 अरब से अधिक धागे हैं ... अच्छा, इसके साथ शुभकामनाएँ।

वैसे भी, ThreadPoolExecutor राज्यों के जावाडोक:

ऐसे Integer.MAX_VALUE के रूप में अनिवार्य रूप से एक असीम मूल्य के लिए maximumPoolSize सेट करके, आप पूल समवर्ती कार्यों की एक मनमाना संख्या को समायोजित करने के लिए अनुमति देते हैं। आमतौर पर, कोर और अधिकतम पूल आकार केवल निर्माण पर सेट होते हैं, लेकिन सेटकोरपूलसाइज (int) और setMaximumPoolSize (int) का उपयोग करके उन्हें गतिशील रूप से बदला जा सकता है।

LinkedBlockingQueue की तरह एक समान कार्यरत कतार के साथ, यह मनमाने ढंग से बड़ी क्षमता होनी चाहिए।

+0

क्या डाउनवॉटर की व्याख्या करने की देखभाल होगी? –

+0

धन्यवाद यह भी देखें http://stackoverflow.com/questions/28567238/threadpoolexecutor-does-not-shrink-properly/40384042#40384042 अन्य प्रश्न – Vahid

+0

में हल किए गए अन्य मुद्दों को कम करने के लिए वह इसे बाध्य करना चाहते थे, असंबद्ध नहीं। .. – Xerus

8

जब बढ़ते और सिकुड़ते धागे के साथ मिलते हैं, तो मेरे दिमाग में केवल एक ही नाम आता है: java.util.concurrent पैकेज से कैश्ड थ्रेडपूल।

ExecutorService executor = Executors.newCachedThreadPool(); 

CachedThreadPool() धागा का पुन: उपयोग कर सकते हैं, साथ ही के रूप में जब जरूरत नया सूत्र बना सकते हैं। और हाँ, यदि थ्रेड 60 सेकंड के लिए निष्क्रिय है, तो कैशड्रेडपूल इसे मार देगा। तो यह काफी हल्का है - आपके शब्दों में बढ़ रहा है और घट रहा है!

+6

दाएं लेकिन यह बाध्य नहीं है। – Gray

+0

आप अंतर्निहित ThreadPoolExecutor का उपयोग कर सकते हैं और अधिकतमपूल आकार को मैन्युअल रूप से या यहां तक ​​कि रनटाइम पर भी सेट कर सकते हैं –