2010-09-19 26 views
5

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

कॉल निष्पादित करने के लिए पहले से निर्माण धागे का पुन: उपयोग यदि उपलब्ध हो

मुझे समझ नहीं आता कि यह कैसे लागू किया गया है जाएगा कहते हैं। मैं निष्पादक विधि के निष्पादन विधि में अपने कस्टम थ्रेड उदा।

ExecutorService myCachedPool = Executors.newCachedThreadPool(); 
    myCachedPool.execute(new Runnable(){public void run(){ 
    //do something time consuming 

    }}); 

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

धन्यवाद।

उत्तर

4

ध्यान दें कि यह Executor नहीं है जो start() पर कॉल करता है - यह ExecutorService है। और नहीं, यह दो बार start() पर कॉल नहीं कर रहा है। यह उस कार्य को शुरू नहीं करता है जिसे आप सीधे Thread.start() का उपयोग करके देते हैं ... इसके बजाय, यह थ्रेड पूल की कतार के बारे में जानता है जो थ्रेड शुरू करता है। थ्रेड मूल रूप से तब तक इंतजार करेगा जब तक कि कुछ काम न हो, फिर प्रतीक्षा करें और इंतजार करने से पहले इसे निष्पादित करें। तो हालांकि धागा कई कार्यों को निष्पादित करता है, Thread.start() केवल एक बार बुलाया जाता है।

संपादित करें: टिप्पणियों के आधार पर, आप Runnable (जिसे निष्पादित करने का कार्य है) और Thread (जो कार्य निष्पादित करता है) के बीच के अंतर के बारे में थोड़ा उलझन में हैं।

एक ही धागा कई कार्यों को निष्पादित कर सकता है। एक थ्रेड पूल का उपयोग नहीं कर एक बहुत ही सरल उदाहरण के लिए, इस पर विचार करें:

(एक से अधिक थ्रेड से एक List<T> का उपयोग करने का संभावित धागा सुरक्षा के मुद्दों पर ध्यान न दें।)

आप Runnable कार्यों की एक पूरी गुच्छा बना सकते हैं अलग-अलग चीजों को करने में सक्षम, फिर बदले में उन्हें चलाने के लिए एक एकल MultiRunnable बनाएं। MultiRunnable के Thread कन्स्ट्रक्टर में उस उदाहरण को पास करें, और फिर जब आप थ्रेड शुरू करते हैं, तो यह प्रत्येक मूल रनने योग्य कार्यों को निष्पादित करेगा। क्या उससे मदद हुई?

+0

@Jon: माफ करना, मैं तुम्हें खो दिया है। तो ढांचे के आंतरिक धागे का पुन: उपयोग किया जाता है और निष्पादन योग्य नहीं है जिसे मैं निष्पादित करने के लिए तर्क के रूप में पास करता हूं? मेरे धागे को ढांचे में प्रतिनिधि प्रत्येक बार फिर से चालू किया जाएगा, लेकिन ढांचे द्वारा बनाए गए आंतरिक धागे के उसी उदाहरण से? – Cratylus

+0

@ उपयोगकर्ता384706: हां। आपका रननेबल * एक धागा नहीं है - यह केवल एक कार्य निष्पादित किया जाना है। आपको दोनों के बीच अंतर करने की जरूरत है; वे बहुत अलग हैं। –

+0

@ जोन: बहुत बहुत धन्यवाद। केवल एक चीज मुझे यकीन नहीं है, निष्पादकों का उपयोग करने का क्या फायदा है। NewCachedThreadPool(); क्योंकि यदि मेरी कक्षा जो चलने योग्य (एक कार्य के लिए) लागू करती है, उसे तत्काल महंगा किया जाता है, इसे पुन: उपयोग नहीं किया जाएगा और ढांचे का एक ही धागा कार्य के नए उदाहरणों का उपयोग करेगा। तो मैं इस एपीआई से क्या हासिल करूंगा? जब तक अवधारणा यह नहीं है कि प्रत्येक वर्ग जो चलने योग्य लागू करता है वह न्यूनतम है। – Cratylus

5

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

थ्रेड पूल में प्रत्येक थ्रेड केवल wait() निष्पादक के लिए इसे एक नया रननेबल करने के लिए कर सकता है, लेकिन थ्रेड की run() विधि पूर्ण नहीं हुई है। यह केवल निष्पादक को दिया जाने वाला एक नया रननेबल की प्रतीक्षा करता है।

+0

तो आपका मतलब है कि जावाडोक में जहां यह कहता है "कि पहले निर्मित धागे का पुन: उपयोग किया जाएगा" यह निष्पादन योग्य पास करने के लिए संदर्भित नहीं है, लेकिन निष्पादकों के ढांचे के आंतरिक धागे? तो मेरा रननेबल थ्रेड पूल के समान थ्रेड द्वारा फिर से चालू किया जाएगा? क्या मैं समझ गया हूं कि आप क्या कह रहे हैं? – Cratylus

+2

आपका रननेबल पुनर्स्थापित नहीं किया जाएगा। आपका रननेबल इंस्टेंस पूल में थ्रेड में से एक को दिया जाएगा। उस धागे की अपनी 'रन()' विधि है, जो आपके रननेबल की 'रन()' विधि द्वारा प्रतिस्थापित नहीं की जा सकती है। थ्रेड की रन() विधि आपके 'रननेबल' की 'रन()' विधि को कॉल करेगी, और उसके बाद आपके 'Runnable.run()' समाप्त होने के बाद, अंततः थ्रेड होगा (कुछ बहीखाता है जो करना होगा) वापस 'प्रतीक्षा' करने के लिए। – jbindel

1

एक से अधिक धागे को "शुरू" करने के लिए, एक रननेबल बनाएं। उदाहरण के लिए:

//NO 
private class T extends Thread { //not necessary to implement runnable 
    public void run(){ 
     //... 
    } 
} 
void someMethod(){ 
    T a = new T(); 
    a.start(); 
    a.start(); //NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO 
} 

इसके बजाय,

//Yes 
private class T implements Runnable { 
    public void run(){ 
     //... 
    } 
} 
void someMethod(){ 
    T a = new T(); 
    new Thread(a).start(); 
    new Thread(a).start(); //YES YES YES 
} 

यह भी संभव है यह करने के लिए:

void someMethod(){ 
    final Runnable r = new Runnable(){ 
     public void run(){ 
      //... 
     } 
    }; 
    new Thread(r).start(); 
    new Thread(r).start(); 
} 
// r could also be a field of you class.