आकार सीमा के साथ कैश्ड थ्रेड पूल बनाना असंभव है?


127

कैश्ड थ्रेड पूल को थ्रेड की संख्या तक सीमित करना असंभव लगता है जो इसे बना सकता है।

यहाँ बताया गया है कि स्थिर एक्ज़ीक्यूटर्स.newCachedThreadPool मानक जावा लाइब्रेरी में कैसे लागू किया जाता है:

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

तो, एक निश्चित आकार के कैश्ड थ्रेड पूल बनाने के लिए उस टेम्पलेट का उपयोग करना:

new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new SynchronusQueue<Runable>());

अब यदि आप इसका उपयोग करते हैं और 3 कार्य प्रस्तुत करते हैं, तो सब कुछ ठीक हो जाएगा। किसी भी अन्य कार्यों को प्रस्तुत करने से अस्वीकृत निष्पादन अपवाद होंगे।

यह कोशिश कर रहा है:

new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runable>());

क्रमिक रूप से निष्पादित सभी थ्रेड्स में परिणाम होगा। यानी, थ्रेड पूल आपके कार्यों को संभालने के लिए एक से अधिक थ्रेड कभी नहीं बनाएगा।

यह ThreadPoolExecutor की निष्पादित विधि में एक बग है? या शायद यह जानबूझकर है? या कोई और तरीका है?

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


1
क्या पूछते हैं? क्या आपका दूसरा कोड आपके शीर्षक का उत्तर नहीं है?
आरएस

4
मैं एक थ्रेड पूल चाहता हूं जो थ्रेड्स को मांग पर जोड़ देगा क्योंकि कार्यों की संख्या बढ़ती है, लेकिन कभी भी थ्रेड्स की अधिकतम संख्या से अधिक नहीं जोड़ेंगे। कैश्ड थ्रेडपूल पहले से ही ऐसा करता है, सिवाय इसके कि इसमें असीमित संख्या में धागे होंगे और कुछ पूर्व-निर्धारित आकार पर नहीं रुकेंगे। उदाहरणों में मेरे द्वारा परिभाषित आकार 3 है। दूसरा उदाहरण 1 थ्रेड जोड़ता है, लेकिन नए कार्यों के आने के साथ दो और जोड़ नहीं देता है जबकि अन्य कार्य अभी तक पूरे नहीं हुए हैं।
मैट क्रिंकलॉव-वोग्ट

यह जांचें, यह इसे हल करता है, debuggingisfun.blogspot.com/2012/05/…
ethan

जवाबों:


235

The ThreadPoolExecutor में कई महत्वपूर्ण व्यवहार हैं, और आपकी समस्याओं को इन व्यवहारों द्वारा समझाया जा सकता है।

जब कार्य प्रस्तुत किए जाते हैं,

  1. यदि थ्रेड पूल मूल आकार तक नहीं पहुंचा है, तो यह नए थ्रेड बनाता है।
  2. यदि मुख्य आकार तक पहुँच गया है और कोई निष्क्रिय थ्रेड नहीं है, तो यह कार्य को कतारबद्ध करता है।
  3. यदि मूल आकार पहुँच गया है, तो कोई निष्क्रिय थ्रेड नहीं है, और कतार पूर्ण हो जाती है, यह नए थ्रेड बनाता है (जब तक कि यह अधिकतम आकार तक नहीं पहुंचता)।
  4. यदि अधिकतम आकार तक पहुँच गया है, तो कोई निष्क्रिय थ्रेड नहीं है, और कतार पूर्ण हो जाती है, अस्वीकृति नीति अंदर आती है।

पहले उदाहरण में, ध्यान दें कि सिंक्रोनसक्यू का अनिवार्य रूप से आकार 0. है। इसलिए, जिस क्षण आप अधिकतम आकार (3) तक पहुंचते हैं, अस्वीकृति नीति (# 4) में किक करती है।

दूसरे उदाहरण में, चुनाव की कतार एक लिंक्डब्लॉकिंग क्यू है जिसमें असीमित आकार है। इसलिए, आप व्यवहार # 2 के साथ फंस जाते हैं।

आप वास्तव में कैश्ड प्रकार या निश्चित प्रकार के साथ ज्यादा छेड़छाड़ नहीं कर सकते, क्योंकि उनका व्यवहार लगभग पूरी तरह से निर्धारित है।

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

new ThreadPoolExecutor(10, // core size
    50, // max size
    10*60, // idle timeout
    TimeUnit.SECONDS,
    new ArrayBlockingQueue<Runnable>(20)); // queue with a size

परिशिष्ट : यह काफी पुराना उत्तर है, और ऐसा प्रतीत होता है कि JDK ने अपने व्यवहार को बदल दिया है जब यह 0. के मूल आकार में आता है। JDK 1.6 के बाद से, यदि मूल आकार 0 है और पूल में कोई थ्रेड नहीं है, तो थ्रेडपूल एक्ज़ेंडर एक जोड़ देगा उस कार्य को निष्पादित करने के लिए धागा। इसलिए, 0 का मूल आकार ऊपर के नियम का अपवाद है। मेरे ध्यान में लाने के लिए धन्यवाद स्टीव


4
allowCoreThreadTimeOutइस उत्तर को पूर्ण बनाने के लिए आपको विधि के बारे में कुछ शब्द लिखने होंगे । @ User1046052 का उत्तर देखें
hestestupin

1
बहुत बढ़िया जवाब! जोड़ने के लिए सिर्फ एक बिंदु: अन्य अस्वीकृति नीतियां भी ध्यान देने योग्य हैं। @Brianegge
Jeff

1
व्यवहार 2 नहीं कहना चाहिए 'यदि अधिकतम आकार पहुँच गया है और कोई निष्क्रिय थ्रेड नहीं है, तो यह कार्य को कतारबद्ध करता है।' ?
ज़ोल्टन

1
क्या आप इस बारे में विस्तार से बता सकते हैं कि कतार का आकार क्या है? क्या इसका मतलब है कि केवल 20 कार्यों को अस्वीकार किए जाने से पहले ही कतारबद्ध किया जा सकता है?
ज़ोल्टन

1
@ ज़ोल्टन मैंने यह कुछ समय पहले लिखा था, इसलिए एक मौका है कि कुछ व्यवहार तब से बदल सकता है (मैं नवीनतम गतिविधियों का भी बारीकी से पालन नहीं करता था), लेकिन इन व्यवहारों को अपरिवर्तित मानते हुए, # 2 जैसा कहा गया है, सही है और शायद सबसे महत्वपूर्ण (और कुछ हद तक आश्चर्यजनक) इस बात का। एक बार मुख्य आकार तक पहुँचने के बाद, TPE नए धागों को बनाने पर कतार में लग जाता है। कतार का आकार वस्तुतः कतार का आकार है जो TPE को दिया गया है। यदि कतार पूर्ण हो जाती है, लेकिन यह अधिकतम आकार तक नहीं पहुंची है, तो यह एक नया थ्रेड (कार्यों को अस्वीकार नहीं करेगी) बनाएगी। # 3 देखें। उम्मीद है की वो मदद करदे।
sjlee

60

जब तक मैंने कुछ याद नहीं किया, मूल प्रश्न का हल सरल है। निम्नलिखित कोड मूल पोस्टर द्वारा वर्णित वांछित व्यवहार को लागू करता है। यह एक अनबाउंड कतार पर काम करने के लिए 5 थ्रेड तक फैल जाएगा और 60 सेकंड के बाद निष्क्रिय थ्रेड समाप्त हो जाएगा।

tp = new ThreadPoolExecutor(5, 5, 60, TimeUnit.SECONDS,
                    new LinkedBlockingQueue<Runnable>());
tp.allowCoreThreadTimeOut(true);

1
तुम सही हो। उस विधि को jdk 1.6 में जोड़ा गया था, इसलिए बहुत से लोग इसके बारे में नहीं जानते हैं। इसके अलावा, आपके पास "न्यूनतम" कोर पूल का आकार नहीं हो सकता है, जो दुर्भाग्यपूर्ण है।
17

4
इस बारे में मेरी एकमात्र चिंता (JDK 8 डॉक्स से) है: "जब कोई नया कार्य विधि निष्पादन (रन करने योग्य) में प्रस्तुत किया जाता है, और कोरपूलिसाइज थ्रेड्स से कम चल रहे हैं, तो अनुरोध को संभालने के लिए एक नया धागा बनाया जाता है, भले ही अन्य कार्यकर्ता धागे बेकार हैं। ”
वेजाइग

बहुत यकीन है कि यह वास्तव में काम नहीं करता है। पिछली बार मैंने ऊपर देखा था कि वास्तव में आप कभी भी केवल एक धागे में अपना काम चलाते हैं। भले ही आप 5 साल का हो। फिर से, कुछ साल हो गए, लेकिन जब मैंने थ्रेडपूल एक्सक्यूटर के कार्यान्वयन में काम किया, तो आपकी कतार पूरी होने के बाद केवल नए धागे भेजे गए। एक अनबाउंड कतार का उपयोग करने से ऐसा कभी नहीं होता है। आप कार्य और loggin'g थ्रेड नाम को सबमिट करके सो सकते हैं। प्रत्येक रननेबल एक ही नाम को प्रिंट करेगा / किसी अन्य थ्रेड पर नहीं चलाया जाएगा।
मैट क्रिंकलाव-वोग

2
यह काम करता है, मैट। आपने मुख्य आकार को 0 पर सेट किया है, यही कारण है कि आपके पास केवल 1 धागा था। यहाँ ट्रिक को मुख्य आकार को अधिकतम आकार में सेट करना है।
T-Gergely

1
@vegee सही है - यह वास्तव में बहुत अच्छी तरह से काम नहीं करता है - CorePoolSize से ऊपर होने पर थ्रेडपूल एक्सक्यूटर केवल थ्रेड का फिर से उपयोग करेगा। इसलिए जब corePoolSize, maxPoolSize के बराबर हो, तो आपको थ्रेड कैशिंग से तभी लाभ होगा जब आपका पूल भरा हो (इसलिए यदि आप इसका उपयोग करना चाहते हैं, लेकिन आमतौर पर अपने अधिकतम पूल आकार के नीचे रहते हैं, तो आप थ्रेड टाइमआउट को कम कर सकते हैं मूल्य; और अवगत रहें कि कोई कैशिंग नहीं है - हमेशा नए धागे)
क्रिस रिडेल

7

एक ही मुद्दा था। चूंकि कोई अन्य उत्तर सभी मुद्दों को एक साथ नहीं रखता है, इसलिए मैं इसमें जोड़ रहा हूं:

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

इसलिए:

public class MyExecutor extends ThreadPoolExecutor {

    public MyExecutor() {
        super(4, 4, 5,TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
        allowCoreThreadTimeOut(true);
    }

    public void setThreads(int n){
        setMaximumPoolSize(Math.max(1, n));
        setCorePoolSize(Math.max(1, n));
    }

}

यह निष्पादक है:

  1. अधिकतम थ्रेड की कोई अवधारणा नहीं है क्योंकि हम एक अनबाउंड कतार का उपयोग कर रहे हैं। यह एक अच्छी बात है क्योंकि इस तरह की कतार निष्पादक को गैर-कोर, अतिरिक्त थ्रेड बनाने के लिए पैदा कर सकती है यदि यह अपनी सामान्य नीति का पालन करता है।

  2. अधिकतम आकार की एक कतार Integer.MAX_VALUE। लंबित कार्यों की संख्या से अधिक होने पर Submit()फेंक देंगे । निश्चित नहीं कि हम पहले स्मृति से बाहर होंगे या ऐसा होगा।RejectedExecutionExceptionInteger.MAX_VALUE

  3. 4 कोर धागे संभव है। निष्क्रिय कोर थ्रेड्स स्वचालित रूप से बाहर निकलते हैं अगर 5 सेकंड के लिए निष्क्रिय हो। हां, सख्ती से मांग थ्रेड्स पर।नंबर का उपयोग setThreads()करने की विधि का विविध उपयोग किया जा सकता है ।

  4. यह सुनिश्चित करता है कि मुख्य धागों की न्यूनतम संख्या कभी एक से कम न हो, अन्यथा submit()हर कार्य को अस्वीकार कर दिया जाएगा। चूंकि कोर थ्रेड्स की जरूरत है> = अधिकतम थ्रेड्स विधि setThreads()अधिकतम थ्रेड्स सेट करती है, हालांकि एक अनबाउंड कतार के लिए अधिकतम थ्रेड सेटिंग बेकार है।


मुझे लगता है कि आपको 'allowCoreThreadTimeOut' को 'true' पर सेट करने की आवश्यकता है, अन्यथा, एक बार थ्रेड्स बन जाने के बाद, आप उन्हें हमेशा के लिए अपने पास रखेंगे: gist.github.com/ericdcobb/46b81717384f5ca9d5f5d
eric

उफ़ मैं बस चूक गया, क्षमा करें, आपका उत्तर एकदम सही है!
eric

6

आपके पहले उदाहरण में, बाद के कार्यों को अस्वीकार कर दिया गया है क्योंकि AbortPolicyडिफ़ॉल्ट है RejectedExecutionHandler। ThreadPoolExecutor में निम्नलिखित नीतियां शामिल हैं, जिन्हें आप setRejectedExecutionHandlerविधि के माध्यम से बदल सकते हैं :

CallerRunsPolicy
AbortPolicy
DiscardPolicy
DiscardOldestPolicy

ऐसा लगता है कि आप CallerRunsPolicy के साथ कैश्ड थ्रेड पूल चाहते हैं।


5

यहां किसी भी उत्तर ने मेरी समस्या को ठीक नहीं किया, जिसे अपाचे के HTTP क्लाइंट (3.x संस्करण) का उपयोग करके सीमित मात्रा में HTTP कनेक्शन बनाने के साथ करना था। चूंकि मुझे एक अच्छे सेटअप का पता लगाने में कुछ घंटे लगे, मैं साझा करूँगा:

private ExecutorService executor = new ThreadPoolExecutor(5, 10, 60L,
  TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
  Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());

यह ThreadPoolExecutorपांच के साथ शुरू होता है और CallerRunsPolicyनिष्पादन के लिए उपयोग करते हुए एक साथ अधिकतम दस धागे चलाता है ।


इस समाधान के साथ समस्या यह है कि यदि आप संख्या या उत्पादकों को बढ़ाते हैं, तो आप पृष्ठभूमि धागे को चलाने वाले थ्रेड्स की संख्या में वृद्धि करेंगे। कई मामलों में यह नहीं है कि आप क्या चाहते हैं।
ग्रे

3

थ्रेडपूल के लिए Javadoc के अनुसार

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

(जोर मेरा)

घबराना का जवाब वही है जो आप चाहते हैं, हालांकि मेरा आपके दूसरे सवाल का जवाब है। :)


2

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


मुझे लगता है कि आपको आकार 0 (डिफ़ॉल्ट रूप से) से मतलब है, ताकि हर बार नया धागा बनाने के लिए कोई कार्य पंक्तिबद्ध न हो और वास्तव में निष्पादक सेवा हो।
लियोनमैक्स

2

ऐसा नहीं लग रहा है कि कोई भी उत्तर वास्तव में प्रश्न का उत्तर देता है - वास्तव में मैं ऐसा करने का एक तरीका नहीं देख सकता - भले ही आप कई विधियों / संपत्तियों में से किसी एक से उपवर्ग प्राप्त कर लें, क्योंकि कई तरीके निजी हैं जैसे कि addIfUnderaxaximumPoolSize को संरक्षित किया जा सकता है। निम्न कार्य करें:

class MyThreadPoolService extends ThreadPoolService {
    public void execute(Runnable run) {
        if (poolSize() == 0) {
            if (addIfUnderMaximumPoolSize(run) != null)
                return;
        }
        super.execute(run);
    }
}

निकटतम मैं यह था - लेकिन यह भी एक बहुत अच्छा समाधान नहीं है

new ThreadPoolExecutor(min, max, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()) {
    public void execute(Runnable command) {
        if (getPoolSize() == 0 && getActiveCount() < getMaximumPoolSize()) {        
            super.setCorePoolSize(super.getCorePoolSize() + 1);
        }
        super.execute(command);
    }

    protected void afterExecute(Runnable r, Throwable t) {
         // nothing in the queue
         if (getQueue().isEmpty() && getPoolSize() > min) {
             setCorePoolSize(getCorePoolSize() - 1);
         }
    };
 };

पी एस ऊपर परीक्षण नहीं किया


2

यहाँ एक और उपाय है। मुझे लगता है कि यह समाधान जैसा आप चाहते हैं वैसा ही व्यवहार करता है (हालांकि इस समाधान पर गर्व नहीं):

final LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>() {
    public boolean offer(Runnable o) {
        if (size() > 1)
            return false;
        return super.offer(o);
    };

    public boolean add(Runnable o) {
        if (super.offer(o))
            return true;
        else
            throw new IllegalStateException("Queue full");
    }
};

RejectedExecutionHandler handler = new RejectedExecutionHandler() {         
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        queue.add(r);
    }
};

dbThreadExecutor =
        new ThreadPoolExecutor(min, max, 60L, TimeUnit.SECONDS, queue, handler);

2

यह वही है जो आप चाहते हैं (कम से कम मुझे ऐसा लगता है)। एक स्पष्टीकरण की जाँच के लिए जोनाथन Feinberg जवाब

Executors.newFixedThreadPool(int n)

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


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

0
  1. आप @sjleeThreadPoolExecutor द्वारा सुझाए अनुसार उपयोग कर सकते हैं

    आप पूल के आकार को गतिशील रूप से नियंत्रित कर सकते हैं। अधिक विवरण के लिए इस प्रश्न पर एक नज़र डालें:

    डायनेमिक थ्रेड पूल

    या

  2. आप newWorkStealingPool API का उपयोग कर सकते हैं , जिसे java 8 के साथ पेश किया गया है।

    public static ExecutorService newWorkStealingPool()

    सभी उपलब्ध प्रोसेसरों को अपने लक्ष्य समांतरता स्तर के रूप में उपयोग करते हुए एक कार्य-चोरी धागा पूल बनाता है।

डिफ़ॉल्ट रूप से, समानांतरता स्तर आपके सर्वर में CPU कोर की संख्या पर सेट है। यदि आपके पास 4 कोर सीपीयू सर्वर है, तो थ्रेड पूल का आकार 4 होगा। यह एपीआई ForkJoinPoolटाइप करता है ExecutorService और फोर्कजॉइनपूल में व्यस्त थ्रेड्स से कार्यों को चोरी करके निष्क्रिय थ्रेड्स के काम की अनुमति देता है।


0

समस्या को इस प्रकार संक्षेप में प्रस्तुत किया गया था:

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

समाधान की ओर इशारा करने से पहले मैं बताऊंगा कि निम्नलिखित समाधान काम क्यों नहीं करते हैं:

new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());

जब 3 की सीमा समाप्त हो जाती है तो यह किसी भी कार्य को कतारबद्ध नहीं करेगा क्योंकि परिभाषा के अनुसार, SynchronousQueue किसी भी तत्व को पकड़ नहीं सकता है।

new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());

यह एक एकल थ्रेड से अधिक नहीं बनाएगा क्योंकि थ्रेडपूल एक्सक्यूटर केवल कोरपूलसाइज से अधिक धागे बनाता है यदि कतार भरी हुई है। लेकिन LinkedBlockingQueue कभी भरा नहीं होता है।

ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS,
    new LinkedBlockingQueue<Runnable>());
executor.allowCoreThreadTimeOut(true);

CorePoolSize तक पहुंचने तक थ्रेड्स का पुन: उपयोग नहीं किया जाएगा क्योंकि थ्रेडपूल Executor थ्रेड की संख्या बढ़ाता है जब तक कि CorePoolSize तब तक नहीं पहुंचता है जब तक कि मौजूदा थ्रेड्स बेकार हैं। यदि आप इस नुकसान के साथ रह सकते हैं तो यह समस्या का सबसे आसान समाधान है। यह "जावा कॉन्सैरेसी इन प्रैक्टिस" (p172 पर फुटनोट) में वर्णित समाधान भी है।

वर्णित समस्या का एकमात्र पूर्ण समाधान यह प्रतीत होता है कि कतार की offerविधि को ओवरराइड करने और RejectedExecutionHandlerइस प्रश्न के उत्तर में बताए अनुसार लिखना है : कतार से पहले थ्रेड्स को अधिकतम करने के लिए थ्रेडपूल एक्सक्यूलेटर को कैसे प्राप्त करें?


0

यह Java8 + (और अन्य, अभी के लिए ..) के लिए काम करता है

     Executor executor = new ThreadPoolExecutor(3, 3, 5, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>()){{allowCoreThreadTimeOut(true);}};

जहां थ्रेड्स काउंट की सीमा 3 है, और निष्क्रिय थ्रेड्स के लिए 5 टाइमआउट है।

यदि आप यह जाँचना चाहते हैं कि क्या यह अपने आप काम करता है , तो यहाँ काम करने के लिए कोड है:

public static void main(String[] args) throws InterruptedException {
    final int DESIRED_NUMBER_OF_THREADS=3; // limit of number of Threads for the task at a time
    final int DESIRED_THREAD_IDLE_DEATH_TIMEOUT=5; //any idle Thread ends if it remains idle for X seconds

    System.out.println( java.lang.Thread.activeCount() + " threads");
    Executor executor = new ThreadPoolExecutor(DESIRED_NUMBER_OF_THREADS, DESIRED_NUMBER_OF_THREADS, DESIRED_THREAD_IDLE_DEATH_TIMEOUT, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>()) {{allowCoreThreadTimeOut(true);}};

    System.out.println(java.lang.Thread.activeCount() + " threads");

    for (int i = 0; i < 5; i++) {
        final int fi = i;
        executor.execute(() -> waitsout("starting hard thread computation " + fi, "hard thread computation done " + fi,2000));
    }
    System.out.println("If this is UP, it works");

    while (true) {
        System.out.println(
                java.lang.Thread.activeCount() + " threads");
        Thread.sleep(700);
    }

}

static void waitsout(String pre, String post, int timeout) {
    try {
        System.out.println(pre);
        Thread.sleep(timeout);
        System.out.println(post);
    } catch (Exception e) {
    }
}

मेरे लिए ऊपर दिए गए कोड का आउटपुट है

1 threads
1 threads
If this is UP, it works
starting hard thread computation 0
4 threads
starting hard thread computation 2
starting hard thread computation 1
4 threads
4 threads
hard thread computation done 2
hard thread computation done 0
hard thread computation done 1
starting hard thread computation 3
starting hard thread computation 4
4 threads
4 threads
4 threads
hard thread computation done 3
hard thread computation done 4
4 threads
4 threads
4 threads
4 threads
3 threads
3 threads
3 threads
1 threads
1 threads
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.