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


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

साथ में 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

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


1797
2018-02-12 14:28


मूल


इस सवाल के लिए धन्यवाद, उत्तरों ने मेरी कई गलत धारणाओं को मंजूरी दे दी। मैंने अस्तित्व में आने से पहले जावा थ्रेड करने का सही तरीका देखा और वहां बहुत सारी गलत जानकारी / पुरानी जानकारी थी। - James McMahon
एक कारण है कि आप थ्रेड का विस्तार करना चाहते हैं (लेकिन मैं इसकी सिफारिश नहीं करता हूं), आप preemptively संभाल सकते हैं interrupt()। फिर, यह एक विचार है, यह सही मामले में उपयोगी हो सकता है, हालांकि मैं इसकी अनुशंसा नहीं करता हूं। - bestsss
कृपया उत्तर भी देखें, अच्छी तरह से समझाया गया: stackoverflow.com/q/5562720/285594 - YumYumYum
@bestsss, मैं समझने की कोशिश कर रहा हूं कि आप हस्तक्षेप () को संभालने के बारे में क्या कह सकते हैं। क्या आप विधि को ओवरराइड करने की कोशिश कर रहे हैं? - Bob Cross
हां। कोड के अनुसार, वर्ग थ्रेड ए किसी भी वर्ग का विस्तार कर सकता है जबकि कक्षा थ्रेड बी किसी भी अन्य वर्ग का विस्तार नहीं कर सकता है - mani deepak


जवाब:


हाँ: उपकरण Runnable ऐसा करने का पसंदीदा तरीका है, आईएमओ। आप वास्तव में धागे के व्यवहार का विशेषज्ञ नहीं हैं। आप इसे चलाने के लिए कुछ दे रहे हैं। इसका मत रचना है दार्शनिक जाने के लिए "शुद्ध" रास्ता।

में व्यावहारिक शर्तें, इसका मतलब है कि आप कार्यान्वित कर सकते हैं Runnable और एक और कक्षा से भी विस्तार।


1447
2018-02-12 14:32



ठीक है, अच्छी तरह से डाल दिया। थ्रेड में इसे विस्तारित करके हम किस व्यवहार को ओवरराइट करने का प्रयास कर रहे हैं? मैं तर्क दूंगा कि ज्यादातर लोग किसी भी व्यवहार को ओवरराइट करने की कोशिश नहीं कर रहे हैं, लेकिन थ्रेड के व्यवहार का उपयोग करने की कोशिश कर रहे हैं। - hooknc
एक साइड टिप्पणी के रूप में, यदि आप थ्रेड को तुरंत चालू करते हैं और इसकी प्रारंभ () विधि को कॉल नहीं करते हैं तो आप जावा में मेमोरी लीक बना रहे हैं <5 (यह रननेबल के साथ नहीं होता है): stackoverflow.com/questions/107823/... - Nacho Coloma
रननेबल का एक मामूली लाभ यह है कि, यदि कुछ परिस्थितियों में आपको परवाह नहीं है, या थ्रेडिंग का उपयोग नहीं करना चाहते हैं, और आप केवल कोड निष्पादित करना चाहते हैं, तो आपके पास केवल रन () को कॉल करने का विकल्प है। जैसे (बहुत handwavy) if (numberCores > 4) myExecutor.excute(myRunnable); else myRunnable.run() - user949300
@ user949300 आप इसके साथ भी कर सकते हैं extends Thread और यदि आप थ्रेडिंग नहीं चाहते हैं तो आप भी क्यों लागू करेंगे Runnable... - m0skit0
सिएरा और बेट्स को पैराफ्रेश करने के लिए, रननेबल को लागू करने का एक प्रमुख लाभ यह है कि आप वास्तुशिल्प रूप से "धावक" से "नौकरी" को अलग कर रहे हैं। - 8bitjunkie


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

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

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

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

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

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

तो, अगर हम उनकी जगह लेते हैं runnable आपके साथ threadA, हम निम्नलिखित प्राप्त करते हैं:

new FutureTask<Object>(threadA, null)

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

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

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

494
2018-02-12 14:37



यह स्वीकृत उत्तर IMHO से बेहतर है। एक बात: आपके पास कोड का स्निपेट निष्पादक को बंद नहीं करता है और मुझे लाखों प्रश्न दिखाई देते हैं जहां लोगों को यह गलत लगता है, हर बार एक कार्यकर्ता बनने के लिए एक नया निष्पादक बनाते हैं। es स्थिर (या इंजेक्शन) फ़ील्ड के रूप में बेहतर होगा, इसलिए यह केवल एक बार बनाया जाता है। - artbristol
@artbristol, धन्यवाद! मैं नए निष्पादक से असहमत नहीं हूं (हम जो करते हैं वह हमारे कोड में करते हैं)। मूल उत्तर लिखने में, मैं मूल खंड के अनुरूप समान कोड लिखने की कोशिश कर रहा था। हमें उम्मीद है कि इन उत्तरों के कई पाठक उन्हें अंक से कूदने के रूप में उपयोग करेंगे। मैं javadoc के लिए एक प्रतिस्थापन लिखने की कोशिश नहीं कर रहा हूँ। मैं इसके लिए विपणन सामग्री प्रभावी ढंग से लिख रहा हूं: अगर आपको यह विधि पसंद है, तो आपको उन सभी अन्य महान चीजों को देखना चाहिए जो हमें पेश करना है ...! - Bob Cross
मुझे पता है कि मैं इस पर थोड़ा देर से टिप्पणी कर रहा हूं, लेकिन इससे निपट रहा हूं FutureTask आमतौर पर वह नहीं है जो आप करना चाहते हैं। ExecutorServiceएस उचित बना देगा Future जब आप के लिए submit ए Runnable/Callable उनको। इसी तरह के लिए ScheduledExecutorServiceरेत ScheduledFuture जब आप schedule ए Runnable/Callable। - Powerlord
@ पावरलोर्ड, मेरा इरादा कोड के टुकड़े बनाना था जो ओपी के जितना संभव हो सके मिलते थे। मैं मानता हूं कि नया फ्यूचरटास्क इष्टतम नहीं है लेकिन स्पष्टीकरण के प्रयोजनों के लिए यह स्पष्ट है। - Bob Cross


कहानी का नैतिक:

केवल तभी प्रवेश करें जब आप कुछ व्यवहार को ओवरराइड करना चाहते हैं।

या इसके बजाय इसे पढ़ना चाहिए:

कम विरासत, इंटरफेस और अधिक।


226
2018-03-11 15:50



यदि आप एक समवर्ती चल रहे ऑब्जेक्ट बनाना शुरू करते हैं तो यह हमेशा प्रश्न होना चाहिए! क्या आपको थ्रेड ऑब्जेक्ट फ़ंक्शन की भी आवश्यकता है? - Liebertee
थ्रेड से विरासत में होने पर, लगभग हमेशा के व्यवहार को ओवरराइड करना चाहता है run() तरीका। - Warren Dew
आप ए के व्यवहार को ओवरराइड नहीं कर सकते हैं java.lang.Thread ओवरराइड करके run() तरीका। उस स्थिति में आपको ओवरराइड करने की आवश्यकता है start() विधि मुझे लगता है। आम तौर पर आप बस के व्यवहार का पुन: उपयोग करते हैं java.lang.Thread में अपने निष्पादन ब्लॉक इंजेक्शन द्वारा run() तरीका। - sura2k


बहुत अच्छे जवाब, मैं इस पर और अधिक जोड़ना चाहता हूं। यह समझने में मदद करेगा 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() विधि और कोई अन्य थ्रेड विधियों। यह महत्वपूर्ण है क्योंकि कक्षाओं को उप-वर्गीकृत नहीं किया जाना चाहिए जब तक कि प्रोग्रामर वर्ग के मौलिक व्यवहार को संशोधित या बढ़ाने पर इरादा नहीं रखता।

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

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


185
2018-03-05 14:26



आपका कोड पेटेंट गलत है। मेरा मतलब है, यह करता है जो करता है, लेकिन जो आप दिखाने के इरादे से नहीं करते हैं। - zEro
स्पष्टीकरण के लिए: चलने योग्य मामले के लिए आपने एक ही इम्प्लेमेंट्स का उपयोग किया है, कई थ्रेड शुरू करने के लिए ट्यूनेबल उदाहरण, जबकि थ्रेड केस के लिए आप अलग-अलग विस्तार कर रहे हैं थ्रेड इंस्टेंस जो स्पष्ट रूप से आपके द्वारा दिखाए गए व्यवहार की ओर ले जाते हैं। आपकी मुख्य विधि का दूसरा भाग होना चाहिए: ExtendsThread et = new ExtendsThread();  Thread tc1 = new Thread(et);  tc1.start();  Thread.sleep(1000);  Thread tc2 = new Thread(et);  tc2.start();  Thread.sleep(1000);  Thread tc3 = new Thread(et);  tc3.start();  क्या यह कोई स्पष्ट है? - zEro
मैं अभी तक आपके इरादे को समझ नहीं पाया, लेकिन मेरा मुद्दा यह था कि यदि आप विस्तारित थ्रेड के कई उदाहरण बनाते हैं - वे सभी 1 लौटाएंगे (जैसा कि आपने दिखाया है)। आप वही काम करके रननेबल के लिए एक ही परिणाम प्राप्त कर सकते हैं, यानी इम्प्लेमेंट्स के कई उदाहरण बना सकते हैं। - zEro
@ ज़ीरो हाय, मैं भविष्य से हूं। यह देखते हुए कि कोड के आपके संस्करण में है Thread कथन भी है, बयान है 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 तो गलत? यदि नहीं, तो एक मामला क्या है जो इसे प्रदर्शित करता है? - Evil Washing Machine
@EvilWashingMachine: लंबे समय तक निष्क्रिय निष्क्रिय .. और बस यह देखा। मैंने ऑब्जेक्ट के हैशकोड को प्रिंट स्टेटमेंट में जोड़ा है ... + " hashcode: " + this.hashCode() - zEro


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

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


73
2018-02-12 14:51



खैर, आप वास्तव में एक ही चीज़ कर सकते हैं Thread ऑब्जेक्ट भी क्योंकि Thread implements Runnable... ;-) लेकिन यह चीजों को एक साथ "बेहतर महसूस करता है" Runnable एक के साथ उन्हें करने से Thread! - siegi
सच है, लेकिन Thread आपको बहुत सी अतिरिक्त चीजें जोड़ती हैं जिनकी आपको आवश्यकता नहीं है, और कई मामलों में नहीं चाहते हैं। इंटरफ़ेस को लागू करने से आप हमेशा बेहतर होते हैं जो वास्तव में आप जो कर रहे हैं उससे मेल खाते हैं। - Herms


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

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

enter image description here

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

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

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

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

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

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

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

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

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

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

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

जब आप extends Thread कक्षा, आपके प्रत्येक धागे अद्वितीय वस्तु बनाता है और इसके साथ सहयोग करता है। जब आप implements Runnable, यह एक ही वस्तु को कई धागे में साझा करता है।


65
2018-05-11 08:59





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

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

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

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 multithreading प्रतियोगी या प्रतिस्थापन नहीं के लिए एक दूसरे के पूरक हैं।


61
2018-05-12 13:50



ठीक ठीक! यह स्वीकार्य उत्तर होना चाहिए। बीटीडब्ल्यू मुझे लगता है कि सवाल संपादित किया गया है और ThreadA अब समझ में नहीं आता है - idelvall
स्वीकार्य उत्तर आपके लिए प्रतिक्रिया @idelvall के लिए अधिक प्रतिनिधि धन्यवाद है - Saif


आपको रननेबल को लागू करना चाहिए, लेकिन यदि आप जावा 5 या उच्चतर पर चल रहे हैं, तो आपको इसे शुरू नहीं करना चाहिए new Thread लेकिन एक का उपयोग करें ExecutorService बजाय। विवरण के लिए देखें: जावा में सरल थ्रेडिंग को कैसे कार्यान्वित करें


41
2018-02-12 14:41



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


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

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


31
2018-02-12 14:32



चलने योग्य में हम नेटवर्क कॉल नहीं कर सकते हैं, है ना? जैसा कि मेरे पास android.os.NetworkOnMainThreadException है। लेकिन धागे का उपयोग करके मैं नेटवर्क कॉल कर सकता हूं। अगर मैं गलत हूं कृपया मुझे सही। - Nabeel Thobani
@NabeelTobani सामान्य जावा परवाह नहीं है, लेकिन ऐसा लगता है जैसे एंड्रॉइड करता है। मैं एंड्रॉइड के साथ पर्याप्त परिचित नहीं हूं, हालांकि। - Powerlord
@NabeelTobani निश्चित रूप से आप कर सकते हैं। शायद आप अपने रननेबल के साथ थ्रेड नहीं बना रहे हैं। - m0skit0


मैं कहूंगा कि तीसरा तरीका है:

public class Something {

    public void justAnotherMethod() { ... }

}

new Thread(new Runnable() {
   public void run() {
    instanceOfSomething.justAnotherMethod();
   }
}).start();

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


19
2017-10-25 21:41



यह वास्तव में एक तीसरा तरीका नहीं है। आप अभी भी रननेबल को कार्यान्वित कर रहे हैं, बस इसे अनाम रूप से कर रहे हैं। - Don Roby
@ डॉन रॉबी: जो अलग है। यह अक्सर सुविधाजनक होता है, और आप युक्त वर्ग / विधि से फ़ील्ड और अंतिम स्थानीय चर का उपयोग कर सकते हैं। - Bart van Heukelom
हाँ, यह सुविधाजनक है। - Don Roby
@ BartvanHeukelom यह सुविधाजनक है, लेकिन अलग नहीं है। आप इसे किसी भी प्रकार की नेस्टेड कक्षा, यानी आंतरिक कक्षाओं, स्थानीय वर्गों और लैम्ब्डा अभिव्यक्तियों के साथ कर सकते हैं। - xehpuk


जावा 8 के रिलीज के साथ, अब एक तीसरा विकल्प है।

Runnable एक है कार्यात्मक इंटरफेस, जिसका अर्थ है कि इसका उदाहरण लैम्ब्डा अभिव्यक्तियों या विधि संदर्भों के साथ बनाया जा सकता है।

आपका उदाहरण इसके साथ प्रतिस्थापित किया जा सकता है:

new Thread(() -> { /* Code here */ }).start()

या यदि आप एक का उपयोग करना चाहते हैं ExecutorService और एक विधि संदर्भ:

executor.execute(runner::run)

ये आपके उदाहरणों से बहुत कम नहीं हैं, बल्कि उपयोग के अन्य उत्तरों में बताए गए कई फायदों के साथ भी आते हैं Runnable ऊपर Thread, जैसे एकल जिम्मेदारी और रचना का उपयोग करना क्योंकि आप धागे के व्यवहार का विशेषज्ञ नहीं हैं। यदि आपको आवश्यकता हो तो यह एक अतिरिक्त वर्ग बनाने से भी बचाता है Runnable जैसा कि आप अपने उदाहरणों में करते हैं।


16
2017-07-29 11:24



इस जवाब को स्पष्टीकरण की आवश्यकता है। कुछ परेशान होने के बाद, मैंने निष्कर्ष निकाला () -> {} किसी कस्टम तर्क का प्रतिनिधित्व करना चाहिए जिसे किसी को चाहिए? तो यह बेहतर कहा जाएगा () -> { /* Code here */ }? - ToolmakerSteve
@ToolmakerSteve हाँ, संपादित। - Alex