थ्रेड प्रारंभ () और रन करने योग्य रन () के बीच क्या अंतर है


224

कहें कि हमारे पास ये दो रनवे हैं:

class R1 implements Runnable {
    public void run() {  }
    
}

class R2 implements Runnable {
    public void run() {  }
    
}

फिर इसमें क्या अंतर है:

public static void main() {
    R1 r1 = new R1();
    R2 r2 = new R2();

    r1.run();
    r2.run();
}

और इस:

public static void main() {
    R1 r1 = new R1();
    R2 r2 = new R2();
    Thread t1 = new Thread(r1);
    Thread t2 = new Thread(r2);

    t1.start();
    t2.start();
}

जवाबों:


309

पहला उदाहरण: कोई बहु सूत्र नहीं। दोनों एकल (मौजूदा) धागे में निष्पादित होते हैं। कोई धागा निर्माण नहीं।

R1 r1 = new R1();
R2 r2 = new R2();

r1और r2कक्षाओं की सिर्फ दो अलग-अलग ऑब्जेक्ट हैं जो Runnableइंटरफ़ेस को लागू करते हैं और इस प्रकार run()विधि को लागू करते हैं । जब आप कॉल r1.run()करते हैं तो आप इसे वर्तमान थ्रेड में निष्पादित कर रहे हैं।

दूसरा उदाहरण: दो अलग-अलग धागे।

Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);

t1और t2कक्षा की वस्तुएं हैं Thread। जब आप कॉल करते हैं t1.start(), तो यह एक नया थ्रेड शुरू करता है और आंतरिक रूप से उस नए थ्रेड के भीतर निष्पादित करने के लिए run()विधि कहता है r1


5
कौलड मैं मानता हूं कि इससे पहले कि हम थ्रेड # स्टार्ट () कहते हैं, वास्तव में ओएस थ्रेड के सापेक्ष कुछ भी नहीं होता है? यह केवल एक जावा वस्तु है।
जस्कय

4
यह प्रलेखन के अनुसार सही है। थ्रेड ऑब्जेक्ट आरंभीकरण कोड की जाँच करें, जो प्रलेखन के अनुरूप है। स्रोत कोड में भी, यह है start(), जो एक नेटवी विधि कह रहा है, जो कि ओएस थ्रेड से संबंधित चीजें होनी चाहिए।
भेश गुरुंग

3
थ्रेड कंस्ट्रक्टर डॉक्स यहाँ है । थ्रेड ऑब्जेक्ट आरंभीकरण स्रोत यहाँ हैstart()विधि स्रोत यहाँ है
भेश गुरुंग

92

यदि आप run()सीधे सीधे आह्वान करते हैं, तो इसे कॉलिंग थ्रेड पर निष्पादित किया जाता है, किसी अन्य विधि कॉल की तरह। Thread.start()वास्तव में एक नया धागा बनाने के लिए आवश्यक है ताकि रननेबल की runविधि समानांतर में निष्पादित हो।


2
हॉटस्पॉट जेवीएम में, जावा धागे और देशी धागे के बीच एक सीधा मानचित्रण है। Thread.start()मंगलाचरण धागा राज्य को नए राज्य से रननीय अवस्था में ले जाता है। Runnable का मतलब यह नहीं है कि धागा चल रहा है। एक बार मूल धागा आरंभीकृत होने के बाद, मूल धागा run()जावा धागे में विधि को लागू करता है, जो थ्रेडेबल से रनिंग के लिए थ्रेड स्थिति को बदलता है । जब थ्रेड मूल और जावा थ्रेड दोनों के लिए सभी संसाधनों को समाप्त कर देता है।
overexchange

@overexchange मुझे राज्य बदलने की सामग्री कहां मिल सकती है।
twlkyao

73

अंतर यह है कि Thread.start()एक थ्रेड शुरू होता है जो run()विधि को कॉल करता है, जबकि Runnable.run()सिर्फ run()वर्तमान थ्रेड पर विधि को कॉल करता है ।


35

अंतर यह है कि जब कार्यक्रम कहता है start()विधि, एक नया धागा बनाया जाता है और कोड के अंदर run()में निष्पादित किया जाता है नया धागा, जबकि अगर आप फोन run()विधि सीधे कोई नया धागा बनाया जाएगा और कोड के अंदर run()वर्तमान सूत्र में सीधे निष्पादित करेंगे।

एक और अंतर के बीच start()और run()जावा धागे में है कि आप है नहीं कर सकते हैं फोन start()दो बार। एक बार शुरू होने के बाद, दूसरी start()कॉल IllegalStateExceptionजावा में फेंक देगी जबकि आप run()कई बार कॉल कर सकते हैं क्योंकि यह सिर्फ एक साधारण तरीका है।


21

वास्तव में Thread.start()एक नया धागा बनाता है और इसका निष्पादन परिदृश्य है।

Thread.start()run()विधि को अतुल्यकालिक रूप से कॉल करता है , जो नए थ्रेड की स्थिति को रननेबल में बदल देता है।

लेकिन Thread.run()कोई नया सूत्र नहीं बनाता। इसके बजाय यह वर्तमान में चल रहे धागे में रन विधि को सिंक्रोनाइज़ करता है।

यदि आप उपयोग कर रहे हैं Thread.run()तो आप मल्टी थ्रेडिंग की सुविधाओं का उपयोग नहीं कर रहे हैं।


8

आह्वान run()कॉलिंग थ्रेड पर निष्पादित हो रहा है, किसी अन्य विधि कॉल की तरह। जबकि Thread.start()एक नया धागा बनाता है। आह्वान run()एक प्रोग्रामेटिक बग है।


7

यदि आप run()मुख्य विधि में करते हैं , तो मुख्य विधि का धागा उस runविधि की जगह लेगा , जिस धागे को आपको चलाने की आवश्यकता है।

start()विधि नया थ्रेड बनाता है और जिसके लिए run()विधि किया जा सकता है


'मुख्य विधि' का इससे कोई लेना-देना नहीं है।
लोर्न

3
@EJP, mainलेखक द्वारा कॉलिंग विधि का मतलब है। उनका जवाब काफी अच्छा है। +1 ;-)
dom_beau

1
@dom_beau अगर वह वही है जिसका मतलब है कि उसे ऐसा कहना चाहिए था। उसने जो कहा वह गलत था। इस उत्तर के बारे में 'काफी अच्छा' कुछ भी नहीं है। यह सिर्फ एक उलझन है।
लोर्ने का मार्की

5

t.start() यह वह विधि है जो लाइब्रेरी आपके कोड को कॉल करने के लिए प्रदान करती है जब आप एक नया धागा चाहते हैं।

r.run()वह विधि है जिसे आप लाइब्रेरी के लिए नए थ्रेड में कॉल करने के लिए प्रदान करते हैं ।


इनमें से अधिकांश उत्तर बड़ी तस्वीर को याद करते हैं, जो कि, जहां तक ​​जावा भाषा का संबंध है, किसी भी अन्य दो विधियों के बीच t.start()और अंतर नहीं r.run()है।

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

सबसे बड़ा अंतर यह है कि के लिए कोड के सबसे अधिक है t.start()है देशी कोड, जबकि, ज्यादातर मामलों में, के लिए कोड r.run()शुद्ध होने के लिए जावा जा रहा है। लेकिन यह बहुत अंतर नहीं है। कोड है। मूल कोड खोजने के लिए कठिन है, और समझने में कठिन है जब आप इसे ढूंढते हैं, लेकिन यह अभी भी कोड है जो कंप्यूटर को बताता है कि क्या करना है।

तो, क्या करता t.start()है?

यह एक नया देशी धागा बनाता है, यह उस धागे को कॉल करने की व्यवस्था करता है t.run(), और फिर यह ओएस को नए धागे को चलाने के लिए कहता है। फिर लौट आता है।

और क्या करता r.run()है?

मजेदार बात यह है कि, यह सवाल पूछने वाला व्यक्ति वह व्यक्ति है जिसने इसे लिखा हैr.run()जो कुछ भी आप (यानी, डेवलपर जिसने इसे लिखा है) ने इसे करने के लिए डिज़ाइन किया है।


4

Thread.start()कोड अनुसूचक के साथ थ्रेड को पंजीकृत करता है और अनुसूचक run()विधि को कॉल करता है। इसके अलावा, Threadक्लास है जबकि Runnableएक इंटरफ़ेस है।


3

बिंदु, कि बनाए गए सदस्य बिलकुल ठीक हैं इसलिए मैं केवल कुछ जोड़ना चाहता हूं। बात यह है कि जावा कोई बहु-विरासत का समर्थन नहीं करता है। लेकिन क्या होगा यदि आप एक वर्ग बी को दूसरे वर्ग ए से प्राप्त करना चाहते हैं, लेकिन आप केवल एक कक्षा से प्राप्त कर सकते हैं। अब समस्या यह है कि दोनों वर्गों से "व्युत्पन्न" कैसे करें: ए और थ्रेड। इसलिए आप Runnable Interface का उपयोग कर सकते हैं।

public class ThreadTest{
   public void method(){
      Thread myThread = new Thread(new B());
      myThread.start;
   }
}

public class B extends A implements Runnable{...


1

यदि आप सीधे कॉल run()विधि करते हैं, तो आप कॉल -थ्रेड के run()भाग के रूप में निष्पादित होने के बाद से मल्टी-थ्रेडिंग सुविधा का उपयोग नहीं कर रहे हैं ।

यदि आप start()थ्रेड पर विधि कहते हैं , तो जावा वर्चुअल मशीन रन () विधि कहेगी और दो थ्रेड समवर्ती रूप से चलेंगे - करंट थ्रेड ( main()आपके उदाहरण में) और अन्य थ्रेड (आपके उदाहरण में रन करने योग्य r1)।

थ्रेड वर्गstart() में विधि के स्रोत कोड पर एक नज़र है

 /**
     * Causes this thread to begin execution; the Java Virtual Machine
     * calls the <code>run</code> method of this thread.
     * <p>
     * The result is that two threads are running concurrently: the
     * current thread (which returns from the call to the
     * <code>start</code> method) and the other thread (which executes its
     * <code>run</code> method).
     * <p>
     * It is never legal to start a thread more than once.
     * In particular, a thread may not be restarted once it has completed
     * execution.
     *
     * @exception  IllegalThreadStateException  if the thread was already
     *               started.
     * @see        #run()
     * @see        #stop()
     */
    public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        group.add(this);
        start0();
        if (stopBeforeStart) {
            stop0(throwableFromStop);
        }
    }

    private native void start0();

उपरोक्त कोड में, आप run()विधि के लिए मंगलाचरण नहीं देख सकते हैं ।

private native void start0()कॉलिंग run()विधि के लिए जिम्मेदार है । जेवीएम इस मूल विधि को कार्यान्वित करता है।


0

पहले मामले में आप केवल और वस्तुओं की run()विधि का आह्वान कर रहे हैं।r1r2

दूसरे मामले में आप वास्तव में 2 नए धागे बना रहे हैं!

start()run()कुछ बिंदु पर फोन करेंगे !


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

0

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

प्रारंभ विधि: - थ्रेड वर्ग में परिभाषित किया गया है। जब थ्रेड विधि को थ्रेड ऑब्जेक्ट पर बुलाया जाता है 1- इसे आंतरिक रूप से देशी (नॉनजवा) विधि कहा जाता है जिसे start0 () कहा जाता है; तरीका।

start0 (); विधि: कम प्रसंस्करण (एक धागे के लिए स्टैक निर्माण और प्रोसेसर कतार में धागा आवंटित करने के लिए) के लिए जिम्मेदार है इस बिंदु पर हमारे पास तैयार / रननीय अवस्था में एक धागा है।

2- ऐसे समय में जब थ्रेड शेड्यूलर यह तय करता है कि एक थ्रेड प्रोसेसर प्रोसेसर में प्रवेश करता है (थ्रेड प्राथमिकता के साथ-साथ ओएस शेड्यूलिंग एल्गोरिदम) रन विधि को रननेबल ऑब्जेक्ट (चाहे वह वर्तमान में रन करने योग्य थ्रेड ऑब्जेक्ट या रनने योग्य ऑब्जेक्ट पारित हो) पर लागू किया जाता है थ्रेड कंस्ट्रक्टर) यहां एक थ्रेड रनिंग स्थिति में प्रवेश करता है और अपने कार्य (रन विधि) को निष्पादित करना शुरू करता है


-2

थ्रेड क्लास में अलग-अलग स्टार्ट () और रन () तरीके थ्रेडेड प्रोग्राम बनाने के दो तरीके प्रदान करते हैं। प्रारंभ () विधि नए धागे का निष्पादन शुरू करती है और रन () विधि को बुलाती है। प्रारंभ () विधि तुरंत वापस आती है और नया धागा सामान्य रूप से रन () विधि के लौटने तक जारी रहता है।

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

आपके थ्रेडेड प्रोग्राम की प्रकृति के आधार पर, थ्रेड रन () विधि को कॉल करके सीधे स्टार्ट () विधि के माध्यम से कॉलिंग के समान आउटपुट दे सकता है, लेकिन बाद वाले मामले में कोड वास्तव में एक नए थ्रेड में निष्पादित होता है।


2
`रन () 'को कॉल करना थ्रेडेड प्रोग्राम बनाने का तरीका नहीं है। एक ही रास्ता है।
लोर्न

-2

थ्रेड विस्तारित वर्ग और Runnable उपकरण इंटरफ़ेस के प्रारंभ () विधि कॉल रन ओवरराइड विधि।

लेकिन रन कॉल करके () यह रन विधि की खोज करता है लेकिन यदि वर्ग रनने योग्य इंटरफ़ेस को लागू करता है तो यह रनवे को कॉल करता है।

पूर्व .:

`

public class Main1
{
A a=new A();
B b=new B();
a.run();//This call run() of Thread because run() of Thread only call when class 
        //implements with Runnable not when class extends Thread.
b.run();//This not run anything because no run method found in class B but it 
        //didn't show any error.

a.start();//this call run() of Thread
b.start();//this call run() of Thread
}

class A implements Runnable{
@Override
    public void run() {
            System.out.println("A ");
    }
}

class B extends Thread {

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

`

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.