java - "लागू रननेबल" बनाम "थ्रेड फैलाता है"




multithreading runnable (20)

जावा में धागे के साथ मैंने किस समय बिताया है, मैंने धागे लिखने के इन दो तरीकों को पाया है:

उपकरण के साथ implements Runnable :

public class MyRunnable implements Runnable {
    public void run() {
        //Code
    }
}
//Started with a "new Thread(new MyRunnable()).start()" call

या, extends Thread साथ:

public class MyThread extends Thread {
    public MyThread() {
        super("MyThread");
    }
    public void run() {
        //Code
    }
}
//Started with a "new MyThread().start()" call

कोड के इन दो ब्लॉक में कोई महत्वपूर्ण अंतर है?


  1. जावा एकाधिक विरासत का समर्थन नहीं करता है, जिसका अर्थ है कि आप केवल जावा में एक वर्ग का विस्तार कर सकते हैं ताकि एक बार जब आप Thread क्लास बढ़ाएंगे तो आप अपना मौका खो देंगे और जावा में किसी अन्य वर्ग का विस्तार या उत्तराधिकारी नहीं बना सकते हैं।
  2. ऑब्जेक्ट उन्मुख प्रोग्रामिंग में कक्षा का विस्तार करने का मतलब आम तौर पर नई कार्यक्षमता, संशोधन या व्यवहार में सुधार करना है। यदि हम Thread पर किसी भी संशोधन को इसके बजाय Runnable इंटरफ़ेस का उपयोग करने से नहीं कर रहे हैं।
  3. Runnable इंटरफेस एक Task प्रतिनिधित्व करता है जिसे किसी भी सादे Thread या Executors या किसी अन्य माध्यम से निष्पादित किया जा सकता है। तो Thread से Runnable Task लॉजिकल अलगाव अच्छा डिजाइन निर्णय है।
  4. कार्य को चलाने योग्य के रूप में अलग करने का अर्थ है कि हम कार्य का पुन: उपयोग कर सकते हैं और इसे विभिन्न तरीकों से निष्पादित करने की स्वतंत्रता भी है। चूंकि आप इसे पूरा करने के बाद Thread पुनरारंभ नहीं कर सकते हैं, फिर से कार्य के लिए Runnable बनाम Thread , Runnable विजेता है।
  5. Java designer recognizes this and that's why Executors accept Runnable as Task and they have worker thread which executes those task.
  6. Inheriting all Thread methods are additional overhead just for representing a Task which can can be done easily with Runnable .

असल में, एक दूसरे के साथ Runnable और Thread तुलना करना बुद्धिमान नहीं है।

मोटर वाहन के Wheel and Engine रिश्ते की तरह इन दोनों की बहु-थ्रेडिंग में निर्भरता और रिश्ते है।

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

runnable:
interface Runnable कार्यान्वित करते समय interface Runnable मतलब है कि आप कुछ ऐसा बना रहे हैं जो एक अलग थ्रेड में run able हो। अब कुछ थ्रेड (थ्रेड के अंदर चलने योग्य) के अंदर चलने वाला कुछ बनाना, इसका मतलब थ्रेड बनाना नहीं है।
तो कक्षा MyRunnable एक void run वर्ग के साथ एक सामान्य वर्ग के अलावा कुछ भी नहीं है। और यह वस्तुएं कुछ सामान्य वस्तुएं होंगी जिनमें केवल एक विधि run जो सामान्य रूप से निष्पादित होने पर निष्पादित होगी। (जब तक हम वस्तु को धागे में पास नहीं करते)।

धागा:
class Thread , मैं एक नया थ्रेड शुरू करने की क्षमता वाला एक बहुत ही विशेष वर्ग कहूंगा जो वास्तव में अपनी start() विधि के माध्यम से बहु-थ्रेडिंग को सक्षम बनाता है।

तुलना करने के लिए बुद्धिमान क्यों नहीं?
क्योंकि हमें दोनों को बहु-थ्रेडिंग के लिए आवश्यकता है।

बहु थ्रेडिंग के लिए हमें दो चीजों की आवश्यकता है:

  • ऐसा कुछ जो थ्रेड (रननेबल) के अंदर चलाया जा सकता है।
  • कुछ ऐसा जो एक नया थ्रेड (थ्रेड) शुरू कर सकता है।

इसलिए तकनीकी रूप से और सैद्धांतिक रूप से दोनों धागे को शुरू करने के लिए जरूरी है, कोई दौड़ जाएगा और कोई इसे चलाएगा (मोटर वाहन के Wheel and Engine की तरह)।

यही कारण है कि आप MyRunnable साथ धागा शुरू नहीं कर सकते हैं, आपको इसे Thread उदाहरण में पास करने की आवश्यकता है।

लेकिन class Thread का उपयोग करके केवल थ्रेड बनाना और चलाने के लिए संभव है क्योंकि क्लास Thread Runnable लागू करता है, इसलिए हम सभी जानते हैं कि Thread भी एक Runnable है।

अंत में Thread और Runnable मल्टीथ्रेडिंग के लिए प्रतिद्वंद्वी या प्रतिस्थापन के लिए एक दूसरे के पूरक हैं।


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


एक बात जो मैं आश्चर्यचकित हूं, अभी तक उल्लेख नहीं किया गया है कि Runnable लागू करने से आपकी कक्षा अधिक लचीला हो जाती है।

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


चलने योग्य क्योंकि:

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

भले ही आपको इनमें से किसी की आवश्यकता नहीं है, फिर भी आप भविष्य में हो सकते हैं। चूंकि थ्रेड को ओवरराइड करने का कोई फायदा नहीं है, इसलिए रननेबल एक बेहतर समाधान है।


चूंकि यह एक बहुत ही लोकप्रिय विषय है और अच्छे उत्तरों को पूरी तरह से फैलाया गया है और बड़ी गहराई से निपटाया गया है, मुझे लगा कि दूसरों के अच्छे उत्तरों को अधिक संक्षिप्त रूप में संकलित करना उचित है, इसलिए नए आने वालों के पास एक आसान अवलोकन है:

  1. आप आमतौर पर कार्यक्षमता जोड़ने या संशोधित करने के लिए कक्षा का विस्तार करते हैं। इसलिए, यदि आप किसी भी थ्रेड व्यवहार को ओवरराइट नहीं करना चाहते हैं , तो रननेबल का उपयोग करें।

  2. उसी रोशनी में, यदि आपको थ्रेड विधियों का उत्तराधिकारी करने की आवश्यकता नहीं है , तो आप रननेबल का उपयोग कर उस ओवरहेड के बिना कर सकते हैं।

  3. एकल विरासत : यदि आप थ्रेड का विस्तार करते हैं तो आप किसी भी अन्य वर्ग से विस्तार नहीं कर सकते हैं, इसलिए यदि आपको ऐसा करने की ज़रूरत है, तो आपको रननेबल का उपयोग करना होगा।

  4. तकनीकी तर्कों से डोमेन तर्क को अलग करने के लिए यह एक अच्छा डिज़ाइन है, इस अर्थ में आपके धावक से अपने कार्य को अलग करने के लिए एक रननेबल कार्य होना बेहतर है।

  5. आप एक ही रननेबल ऑब्जेक्ट को कई बार निष्पादित कर सकते हैं, थ्रेड ऑब्जेक्ट, हालांकि, केवल एक बार शुरू किया जा सकता है। (शायद कारण, क्यों निष्पादक Runnables स्वीकार करते हैं, लेकिन धागे नहीं।)

  6. यदि आप अपना काम रननेबल के रूप में विकसित करते हैं, तो आपके पास अब और भविष्य में इसका उपयोग करने के लिए सभी लचीलापन है । आप इसे निष्पादकों के माध्यम से एक साथ चल सकते हैं लेकिन थ्रेड के माध्यम से भी। और आप अभी भी उसी थ्रेड के भीतर किसी अन्य सामान्य प्रकार / ऑब्जेक्ट के रूप में गैर-समवर्ती रूप से इसका उपयोग / कॉल कर सकते हैं।

  7. यह आपके यूनिट परीक्षणों में कार्य-तर्क और समवर्ती पहलुओं को अलग करना भी आसान बनाता है।

  8. यदि आप इस प्रश्न में रुचि रखते हैं, तो आप कॉलबल और रननेबल के बीच के अंतर में रुचि भी ले सकते हैं।


बहुत अच्छे जवाब, मैं इस पर और अधिक जोड़ना चाहता हूं। इससे Extending v/s Implementing Thread को समझने में मदद मिलेगी।
दो वर्ग फ़ाइलों को बहुत बारीकी से बढ़ाता है और कोड से निपटने के लिए कुछ कठिन हो सकता है।

दोनों दृष्टिकोण एक ही काम करते हैं लेकिन कुछ मतभेद हैं।
सबसे आम अंतर है

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

हालांकि, चलने योग्य और विस्तारित थ्रेड को लागू करने के बीच एक महत्वपूर्ण अंतर यह है
by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance.

निम्नलिखित उदाहरण आपको अधिक स्पष्ट रूप से समझने में मदद करता है

//Implement Runnable Interface...
 class ImplementsRunnable implements Runnable {

private int counter = 0;

public void run() {
    counter++;
    System.out.println("ImplementsRunnable : Counter : " + counter);
 }
}

//Extend Thread class...
class ExtendsThread extends Thread {

private int counter = 0;

public void run() {
    counter++;
    System.out.println("ExtendsThread : Counter : " + counter);
 }
}

//Use above classes here in main to understand the differences more clearly...
public class ThreadVsRunnable {

public static void main(String args[]) throws Exception {
    // Multiple threads share the same object.
    ImplementsRunnable rc = new ImplementsRunnable();
    Thread t1 = new Thread(rc);
    t1.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    Thread t2 = new Thread(rc);
    t2.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    Thread t3 = new Thread(rc);
    t3.start();

    // Creating new instance for every thread access.
    ExtendsThread tc1 = new ExtendsThread();
    tc1.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    ExtendsThread tc2 = new ExtendsThread();
    tc2.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    ExtendsThread tc3 = new ExtendsThread();
    tc3.start();
 }
}

उपर्युक्त कार्यक्रम का आउटपुट।

ImplementsRunnable : Counter : 1
ImplementsRunnable : Counter : 2
ImplementsRunnable : Counter : 3
ExtendsThread : Counter : 1
ExtendsThread : Counter : 1
ExtendsThread : Counter : 1

रननेबल इंटरफ़ेस दृष्टिकोण में, कक्षा का केवल एक उदाहरण बनाया जा रहा है और इसे विभिन्न धागे द्वारा साझा किया गया है। इसलिए काउंटर का मूल्य प्रत्येक थ्रेड एक्सेस के लिए बढ़ाया जाता है।

जबकि, थ्रेड क्लास दृष्टिकोण, आपको प्रत्येक थ्रेड एक्सेस के लिए अलग-अलग उदाहरण बनाना होगा। इसलिए प्रत्येक वर्ग के उदाहरणों के लिए अलग-अलग मेमोरी आवंटित की जाती है और प्रत्येक के पास अलग काउंटर होता है, मान समान रहता है, जिसका अर्थ है कि कोई वृद्धि नहीं होगी क्योंकि ऑब्जेक्ट संदर्भ में से कोई भी समान नहीं है।

रननेबल का उपयोग कब करें?
जब आप थ्रेड के समूह से एक ही संसाधन तक पहुंचना चाहते हैं तो रननेबल इंटरफ़ेस का उपयोग करें। यहां थ्रेड क्लास का उपयोग करने से बचें, क्योंकि कई ऑब्जेक्ट्स सृजन अधिक मेमोरी का उपभोग करते हैं और यह एक बड़ा प्रदर्शन ओवरहेड बन जाता है।

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

ज्यादातर मामलों में, रननेबल इंटरफ़ेस का उपयोग किया जाना चाहिए यदि आप केवल run() विधि को ओवरराइड करने और अन्य थ्रेड विधियों को ओवरराइड करने की योजना बना रहे हैं। यह महत्वपूर्ण है क्योंकि कक्षाओं को उप-वर्गीकृत नहीं किया जाना चाहिए जब तक कि प्रोग्रामर कक्षा के मौलिक व्यवहार को संशोधित या बढ़ाने पर इरादा नहीं रखता।

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

मुझे उम्मीद है कि इससे सहायता मिलेगी!


मैं एक विशेषज्ञ नहीं हूं, लेकिन मैं थ्रेड का विस्तार करने के बजाए रननेबल को लागू करने के एक कारण के बारे में सोच सकता हूं: जावा केवल एकल विरासत का समर्थन करता है, ताकि आप केवल एक वर्ग का विस्तार कर सकें।

संपादित करें: यह मूल रूप से कहा गया है "एक इंटरफ़ेस को कार्यान्वित करने के लिए कम संसाधनों की आवश्यकता होती है।" साथ ही, लेकिन आपको किसी भी नए थ्रेड इंस्टेंस को किसी भी तरह से बनाने की आवश्यकता है, इसलिए यह गलत था।


यदि आप किसी अन्य वर्ग को लागू या विस्तारित करना चाहते हैं तो Runnable इंटरफ़ेस अन्यथा बेहतर है यदि आप किसी अन्य वर्ग को विस्तार या कार्यान्वित नहीं करना चाहते हैं तो Thread क्लास बेहतर है

सबसे आम अंतर है

जब आप extends Thread क्लास को बढ़ाते हैं, उसके बाद आप किसी भी अन्य वर्ग को विस्तारित नहीं कर सकते हैं। (जैसा कि आप जानते हैं, जावा एक से अधिक कक्षा में विरासत की अनुमति नहीं देता है)।

जब आप implements Runnable करते हैं, तो आप भविष्य में या अब किसी भी अन्य वर्ग को विस्तारित करने के लिए अपनी कक्षा के लिए एक स्थान सहेज सकते हैं।

  • जावा एकाधिक विरासत का समर्थन नहीं करता है, जिसका अर्थ है कि आप केवल जावा में एक वर्ग का विस्तार कर सकते हैं ताकि एक बार जब आप थ्रेड क्लास बढ़ाएंगे तो आप अपना मौका खो देंगे और जावा में किसी अन्य वर्ग का विस्तार या उत्तराधिकारी नहीं बना सकते हैं।

  • ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग में कक्षा को विस्तारित करने का मतलब आम तौर पर नई कार्यक्षमता, संशोधन या व्यवहार में सुधार करना है। अगर हम थ्रेड पर कोई संशोधन नहीं कर रहे हैं तो इसके बजाए रननेबल इंटरफ़ेस का उपयोग करें।

  • रननेबल इंटरफेस एक कार्य का प्रतिनिधित्व करता है जिसे किसी भी सादे थ्रेड या एक्जिक्यूटर्स या किसी अन्य माध्यम से निष्पादित किया जा सकता है। तो थ्रेड से चलने योग्य कार्य के लॉजिकल अलगाव अच्छा डिजाइन निर्णय है।

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

  • जावा डिजाइनर इसे पहचानता है और यही कारण है कि निष्पादक कार्य के रूप में रननेबल स्वीकार करते हैं और उनके पास कार्यकर्ता धागा होता है जो उन कार्यों को निष्पादित करता है।

  • सभी थ्रेड विधियों को विरासत में केवल एक कार्य का प्रतिनिधित्व करने के लिए अतिरिक्त ओवरहेड होता है जिसे रननेबल के साथ आसानी से किया जा सकता है।

javarevisited.blogspot.com से सौजन्य

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

हालांकि, महत्वपूर्ण अंतर है।

जब आप extends Thread क्लास को बढ़ाते हैं, तो आपका प्रत्येक थ्रेड अद्वितीय ऑब्जेक्ट बनाता है और इसके साथ सहयोग करता है। जब आप implements Runnable करते हैं, तो यह एक ही ऑब्जेक्ट को एकाधिक थ्रेड पर साझा करता है।


यहां हर कोई ऐसा लगता है कि रननेबल को लागू करने का तरीका है और मैं वास्तव में उनके साथ असहमत नहीं हूं लेकिन मेरी राय में थ्रेड बढ़ाने का भी एक मामला है, वास्तव में आपने इसे अपने कोड में प्रदर्शित किया है।

यदि आप रननेबल को लागू करते हैं तो रननेबल लागू करने वाली कक्षा का थ्रेड नाम पर कोई नियंत्रण नहीं होता है, यह कॉलिंग कोड है जो थ्रेड नाम सेट कर सकता है, जैसे:

new Thread(myRunnable,"WhateverNameiFeelLike");

लेकिन यदि आप थ्रेड का विस्तार करते हैं तो आपको इसे कक्षा के भीतर ही प्रबंधित करना होगा (जैसे कि आपके उदाहरण में आप थ्रेड 'थ्रेडबी' नाम दें)। इस मामले में आप:

ए) इसे डीबगिंग उद्देश्यों के लिए एक और उपयोगी नाम दे सकता है

बी) इस वर्ग के सभी उदाहरणों के लिए उस नाम का उपयोग किया जा रहा है (जब तक कि आप इस तथ्य को अनदेखा न करें कि यह एक धागा है और इसके साथ उपर्युक्त है जैसे कि यह एक रननेबल है लेकिन हम किसी भी मामले में यहां सम्मेलन के बारे में बात कर रहे हैं उस संभावना को अनदेखा करें जो मुझे लगता है)।

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

यह एक छोटी सी चीज की तरह प्रतीत हो सकता है, लेकिन जहां आपके पास बहुत सारे धागे के साथ बहुत ही जटिल अनुप्रयोग है और अचानक चीजें 'बंद हो गई हैं' (या तो डेडलॉक के कारणों के लिए या संभवतः नेटवर्क प्रोटोकॉल में दोष की वजह से जो कम होगा स्पष्ट - या अन्य अंतहीन कारण) फिर जावा से एक स्टैक डंप प्राप्त करना जहां सभी धागे को 'थ्रेड -1', 'थ्रेड -2', 'थ्रेड -2' कहा जाता है, हमेशा थ्रेड-3 नहीं होता है (यह इस बात पर निर्भर करता है कि आपके धागे कैसे हैं संरचित और क्या आप उपयोगी रूप से बता सकते हैं कि केवल उनके स्टैक ट्रेस द्वारा कौन सा है - यदि आप एक ही कोड को चलाने वाले एकाधिक धागे के समूह का उपयोग कर रहे हैं तो हमेशा संभव नहीं है)।

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

कॉलिंग स्टैक ट्रेस के साथ जेनेरिक थ्रेड का एक उदाहरण यहां दिया गया है:

public class DebuggableThread extends Thread {
    private static String getStackTrace(String name) {
        Throwable t= new Throwable("DebuggableThread-"+name);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(os);
        t.printStackTrace(ps);
        return os.toString();
    }

    public DebuggableThread(String name) {
        super(getStackTrace(name));
    }

    public static void main(String[] args) throws Exception {
        System.out.println(new Thread());
        System.out.println(new DebuggableThread("MainTest"));
    }
}

और यहां दो नामों की तुलना में आउटपुट का एक नमूना है:

Thread[Thread-1,5,main]
Thread[java.lang.Throwable: DebuggableThread-MainTest
    at DebuggableThread.getStackTrace(DebuggableThread.java:6)
    at DebuggableThread.<init>(DebuggableThread.java:14)
    at DebuggableThread.main(DebuggableThread.java:19)
,5,main]

टीएल; डॉ: उपकरण रननेबल बेहतर है। हालांकि, चेतावनी महत्वपूर्ण है

आम तौर पर, मैं Thread बजाए Runnable जैसे कुछ का उपयोग करने की अनुशंसा करता हूं क्योंकि यह आपको अपने काम को केवल संक्षेप में अपनी पसंद के साथ जोड़कर रखने की अनुमति देता है। उदाहरण के लिए, यदि आप Runnable उपयोग करते हैं और बाद में निर्णय लेते हैं कि वास्तव में इसे अपने स्वयं के Thread की आवश्यकता नहीं है, तो आप केवल threadA.run () को कॉल कर सकते हैं।

चेतावनी: यहां के आसपास, मैं कच्चे धागे के उपयोग को दृढ़ता से हतोत्साहित करता हूं। मैं Callables और FutureTasks का उपयोग करना पसंद करता हूं ( FutureTasks से: "एक रद्द करने योग्य एसिंक्रोनस गणना")। टाइमआउट का एकीकरण, उचित रद्द करने और आधुनिक समवर्ती समर्थन के थ्रेड पूलिंग कच्चे धागे के ढेर की तुलना में मेरे लिए बहुत उपयोगी हैं।

फॉलो-अप: एक FutureTask कन्स्ट्रक्टर है जो आपको रननेबल्स का उपयोग करने की अनुमति देता है (यदि वह वही है जो आप सबसे अधिक आरामदायक हैं) और फिर भी आधुनिक समवर्ती टूल का लाभ प्राप्त करें। जावाडोक उद्धृत करने के लिए:

यदि आपको किसी विशेष परिणाम की आवश्यकता नहीं है, तो फॉर्म के निर्माण का उपयोग करने पर विचार करें:

Future<?> f = new FutureTask<Object>(runnable, null)

इसलिए, अगर हम अपने threadA को अपने threadA साथ बदल देते हैं, तो हमें निम्न मिलता है:

new FutureTask<Object>(threadA, null)

एक और विकल्प जो आपको रननेबल्स के करीब रहने की अनुमति देता है वह ThreadPoolExecutor । आप "भविष्य में कभी-कभी दिए गए कार्य को निष्पादित करने के लिए रननेबल में पास करने के लिए execute विधि का उपयोग कर सकते हैं।"

यदि आप थ्रेड पूल का उपयोग करने का प्रयास करना चाहते हैं, तो उपरोक्त कोड खंड निम्न की तरह कुछ बन जाएगा ( Executors.newCachedThreadPool() फैक्ट्री विधि का उपयोग करके):

ExecutorService es = Executors.newCachedThreadPool();
es.execute(new ThreadA());

Adding my two cents here - Always whenever possible use implements Runnable . Below are two caveats on why you should not use extends Thread s

  1. Ideally you should never extend the Thread class; the Thread class should be made final . At least its methods like thread.getId() . See this discussion for a bug related to extending Thread s.

  2. Those who like to solve puzzles can see another side effect of extending Thread. The below code will print unreachable code when nobody is notifying them.

Please see http://pastebin.com/BjKNNs2G .

public class WaitPuzzle {

    public static void main(String[] args) throws InterruptedException {
        DoNothing doNothing = new DoNothing();
        new WaitForever(doNothing).start();
        new WaitForever(doNothing).start();
        new WaitForever(doNothing).start();
        Thread.sleep(100);
        doNothing.start();
        while(true) {
            Thread.sleep(10);
        }
    }


    static class WaitForever extends  Thread {

        private DoNothing doNothing;

        public WaitForever(DoNothing doNothing) {
            this.doNothing =  doNothing;
        }

        @Override
        public void run() {
            synchronized (doNothing) {
                try {
                    doNothing.wait(); // will wait forever here as nobody notifies here
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Unreachable Code");
            }
        }
    }

    static class DoNothing extends Thread {

        @Override
        public void run() {
            System.out.println("Do Nothing ");
        }
    } 
}

Difference between Extending Thread and Implementing Runnable are:


Difference between Thread and runnable .If we are creating Thread using Thread class then Number of thread equal to number of object we created . If we are creating thread by implementing the runnable interface then we can use single object for creating multiple thread.So single object is shared by multiple Thread.So it will take less memory

So depending upon the requirement if our data is not senstive. So It can be shared between multiple Thread we can used Runnable interface.


If I am not wrong, it's more or less similar to

इंटरफेस और अमूर्त वर्ग के बीच क्या अंतर है?

extends establishes " Is A " relation & interface provides " Has a " capability.

Prefer implements Runnable :

  1. If you don't have to extend Thread class and modify Thread API default implementation
  2. If you are executing a fire and forget command
  3. If You are already extending another class

Prefer " extends Thread " :

  1. If you have to override any of these Thread methods as listed in oracle documentation page

Generally you don't need to override Thread behaviour. So implements Runnable is preferred for most of the times.

On a different note, using advanced ExecutorService or ThreadPoolExecutorService API provides more flexibility and control.

Have a look at this SE Question:

ExecutorService vs Casual Thread Spawner


Java does not support multiple inheritence so if you extends Thread class then no other class will be extended.

For Example: If you create an applet then it must extends Applet class so here the only way to create thread is by implementing Runnable interface


One reason you'd want to implement an interface rather than extend a base class is that you are already extending some other class. You can only extend one class, but you can implement any number of interfaces.

If you extend Thread, you're basically preventing your logic to be executed by any other thread than 'this'. If you only want some thread to execute your logic, it's better to just implement Runnable.


Separating the Thread class from the Runnable implementation also avoids potential synchronization problems between the thread and the run() method. A separate Runnable generally gives greater flexibility in the way that runnable code is referenced and executed.


This is discussed in Oracle's Defining and Starting a Thread tutorial:

Which of these idioms should you use? The first idiom, which employs a Runnable object, is more general, because the Runnable object can subclass a class other than Thread. The second idiom is easier to use in simple applications, but is limited by the fact that your task class must be a descendant of Thread. This lesson focuses on the first approach, which separates the Runnable task from the Thread object that executes the task. Not only is this approach more flexible, but it is applicable to the high-level thread management APIs covered later.

In other words, implementing Runnable will work in scenarios where your class extends a class other than Thread . Java does not support multiple inheritance. Also, extending Thread will not be possible when using some of the high-level thread management APIs. The only scenario where extending Thread is preferable is in a small application that won't be subject to updates in future. It is almost always better to implement Runnable as it is more flexible as your project grows. A design change won't have a major impact as you can implement many interfaces in java, but only extend one class.


Yes, If you call ThreadA call , then not need to call the start method and run method is call after call the ThreadA class only. But If use the ThreadB call then need to necessary the start thread for call run method. If you have any more help, reply me.





java-threads