इस धागे से कोड क्या जुड़ता है?


156

इस कोड में, दो जुड़ने और टूटने का क्या मतलब है? समाप्त होने तक रुकने का t1.join()कारण ?t2t1

Thread t1 = new Thread(new EventThread("e1"));
t1.start();
Thread t2 = new Thread(new EventThread("e2"));
t2.start();
while (true) {
   try {
      t1.join();
      t2.join();
      break;
   } catch (InterruptedException e) {
      e.printStackTrace();
   }
}


3
चूंकि यह ब्लॉक हो जाएगा और थ्रेड समाप्ति की प्रतीक्षा करेगा, तो आपने लूप का उपयोग क्यों किया?
मेहदी

@MahdiElMasaoudi मुझे लगता है, अगर थ्रेड बाधित हो रहा है, तब भी प्रतीक्षा करने के लिए? शायद ऐसा करने का एक शानदार तरीका नहीं है
forresthopkinsa

यदि यह मददगार था तो यहां एक उत्तर को स्वीकार करना याद रखें।
ग्रे

जैसा कि उल्लेख किया गया है, आपको विधि while(true)को कॉल करने की आवश्यकता नहीं है join
चकलादार असफाक आरिफ

जवाबों:


311

इस धागे से कोड क्या जुड़ता है?

Thread.join()विधि javadocs से उद्धृत करने के लिए :

join() इस धागे के मरने की प्रतीक्षा करता है।

एक धागा है जो आपके उदाहरण कोड को चला रहा है जो शायद मुख्य धागा है

  1. मुख्य धागा बनाता है और शुरू होता है t1और t2धागे। दो धागे समानांतर में चलने लगते हैं।
  2. मुख्य धागा कॉल समाप्त t1.join()होने तक प्रतीक्षा करने के लिए कहता है t1
  3. t1धागा पूरा करता है और t1.join()मुख्य थ्रेड में विधि रिटर्न। ध्यान दें कि कॉल करने t1से पहले ही समाप्त हो सकता join()था जिस स्थिति में join()कॉल तुरंत वापस आ जाएगी।
  4. मुख्य धागा कॉल समाप्त t2.join()होने तक प्रतीक्षा करने के लिए कहता है t2
  5. t2धागा कम्प्लिट्स (या इसे पूरा कर सकता है इससे पहले कि t1धागा किया) और t2.join()मुख्य थ्रेड में विधि रिटर्न।

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

t1.join() T1 समाप्त होने तक T2 को रोकने का कारण है?

नहीं। मुख्य धागा जो कॉल t1.join()कर रहा है वह चलना बंद कर देगा और t1धागे के खत्म होने का इंतजार करेगा । t2धागा समानांतर में चल रहा है और से प्रभावित नहीं है t1या t1.join()बिल्कुल भी कहते हैं।

कोशिश / पकड़ के संदर्भ में, join()थ्रो का InterruptedExceptionमतलब है कि मुख्य धागा जो कॉल join()कर रहा है, वह दूसरे धागे से बाधित हो सकता है।

while (true) {

एक whileलूप में जुड़ने का एक अजीब पैटर्न है। आमतौर पर आप पहली बार ज्वाइन करते हैं और फिर दूसरा InterruptedExceptionप्रत्येक मामले में उचित रूप से काम करता है। उन्हें लूप में डालने की आवश्यकता नहीं है।


24
+1 यह एक बहुत ही अजीब पैटर्न है और शायद इसे हटाया जा सकता है।
m0skit0

3
यदि t1 पहले समाप्त होता है, तो t2 समाप्त करने के लिए। यह एक अनुक्रमिक प्रक्रिया प्रतीत होती है। एक धागा पहले खत्म होता है, फिर दूसरा। कई सूत्रण की बात क्या है?
user697911

9
क्योंकि t1और t2समानांतर में चल सकता है। यह सिर्फ इतना है कि mainइससे पहले कि वे इसे जारी रखने के लिए दोनों को पूरा कर सकें। यह एक विशिष्ट पैटर्न @ user697911 है।
ग्रे

3
whileपाश है क्योंकि (मुझे लगता है) यह फिर से प्रयास करना चाहता है join()अगर एक बाधा आती है, कॉल? मैं निश्चित रूप से इसे इस तरह से नहीं लिखूंगा @ user697911।
ग्रे

5
यह सुनिश्चित करने के लिए लूप है कि दोनों t1और t2खत्म। अर्थात। अगर t1फेंकता है InterruptedException, तो यह वापस लूप करेगा और इंतजार करेगा t2। एक विकल्प यह है कि प्रत्येक ट्राय-कैच में दोनों थ्रेड्स का इंतजार किया जाए, ताकि लूप से बचा जा सके। इसके अलावा, EventThreadयह निर्भर करता है , यह इस तरह से करने के लिए समझ में आ सकता है, जैसा कि हम 2 धागे चला रहे हैं, एक नहीं।
माइकल बिस्बर्ज

68

यह एक पसंदीदा जावा साक्षात्कार प्रश्न है।

Thread t1 = new Thread(new EventThread("e1"));
t1.start();
Thread e2 = new Thread(new EventThread("e2"));
t2.start();

while (true) {
    try {
        t1.join(); // 1
        t2.join(); // 2  These lines (1,2) are in in public static void main
        break;
    }
}

t1.join()इसका मतलब है, t1 कुछ कहता है जैसे " मैं पहले खत्म करना चाहता हूं "। उसी के साथ मामला है t2। कोई फर्क नहीं पड़ता कि किसने शुरू किया t1या t2थ्रेड (इस मामले में mainविधि), मुख्य तब तक इंतजार करेंगे t1और t2अपना काम पूरा करेंगे।

हालांकि, एक महत्वपूर्ण बिंदु को नोट करने, t1और t2खुद को समानांतर में पर ध्यान दिए बिना चलाने के कॉल अनुक्रम शामिल हो सकते हैं पर t1और t2। यह वह main/daemonधागा है जिसका इंतजार करना पड़ता है


3
अच्छा उदाहरण। के बारे में "समानांतर में चला सकते हैं": तो क्या? यह महत्वपूर्ण है कि मुख्य धागा t1 के लिए FIRST और t2 के लिए THEN का इंतजार करेगा। यह वास्तव में कोई फर्क नहीं पड़ता कि t1 या t2 मुख्य धागे के दृष्टिकोण से क्या कर रहे हैं
एलेक्स

1
आप "मुख्य / डेमन" धागे का उल्लेख करते हैं। मुख्य मैं समझता हूं लेकिन डेमॉन का इससे कोई लेना-देना नहीं है। मुख्य धागा गैर-डेमॉन है।
ग्रे

1
t1.join(); t2.join();जब तक दोनों धागे समाप्त नहीं हो जाते, तब तक उस जोड़ को निष्पादित करने की अनुमति नहीं देगा। अन्यत्र बहुत ही असामान्य कोड के अभाव में, जुड़ने का क्रम मायने नहीं रखता।
डेविड श्वार्ट्ज

तो t2.join () टी 1 समाप्त होने पर ही कहा जाएगा?
सिंह Droidcoder

दूसरे शब्दों में, यदि हम t1 और t2 थ्रेड्स के निष्पादन को "क्रमबद्ध" करना चाहते हैं, तो हमें t1.join () t1.start () के ठीक बाद रखना होगा क्योंकि मुख्य धागा t1 (और t2 बाद में) शुरू हुआ और निश्चित रूप से इसे हटा दें। पकड़ने की कोशिश। जाहिर है, ऐसा करने पर, परिणाम समानता का नुकसान होगा।
dobrivoje

47

join()एक धागा के पूरा होने की प्रतीक्षा कर रहा है। यह एक अवरोधक विधि है। आपका मुख्य धागा (जो करता है join()) t1.join()लाइन पर इंतजार करेगा जब तक कि t1अपना काम खत्म नहीं हो जाता है, और फिर उसके लिए वही करेंगे t2.join()


29

एक तस्वीर एक हजार शब्दों के बराबर होती है।

    Main thread-->----->--->-->--block##########continue--->---->
                 \                 |               |
sub thread start()\                | join()        |
                   \               |               |
                    ---sub thread----->--->--->--finish    

अधिक उपयोगी के लिए आशा है, और अधिक विवरण के लिए यहां क्लिक करें


3
स्पष्ट और सटीक।
dobrivoje

10

जब थ्रेड टीए कॉल tB.join () इसके कारण न केवल टीबी के मरने या tA के बाधित होने का इंतजार करता है बल्कि tB में अंतिम स्टेटमेंट और tB.join () के बाद अगले स्टेटमेंट के बीच संबंध बनाने से पहले होता है।

किसी थ्रेड में सभी क्रियाएं होती हैं-इससे पहले कि कोई अन्य थ्रेड सफलतापूर्वक उस थ्रेड पर सम्मिलित () से वापस आ जाए।

इसका मतलब है कार्यक्रम

class App {
    // shared, not synchronized variable = bad practice
    static int sharedVar = 0;
    public static void main(String[] args) throws Exception {
        Thread threadB = new Thread(() -> {sharedVar = 1;});
        threadB.start();
        threadB.join();

        while (true) 
            System.out.print(sharedVar);
    }
}

हमेशा प्रिंट करें

>> 1111111111111111111111111 ...

लेकिन कार्यक्रम

class App {
    // shared, not synchronized variable = bad practice
    static int sharedVar = 0;
    public static void main(String[] args) throws Exception {
        Thread threadB = new Thread(() -> {sharedVar = 1;});
        threadB.start();
        // threadB.join();  COMMENT JOIN

        while (true)
            System.out.print(sharedVar);
    }
}

न केवल मुद्रित कर सकते हैं

>> 0000000000 ... 000000111111111111111111111111 ...

परंतु

>> 00000000000000000000000000000000000000000000 ... 

हमेशा केवल '0'।

क्योंकि जावा मेमोरी मॉडल को हेपरेंस-रिलेशन (थ्रेड स्टार्ट, थ्रेड जॉइन, 'सिंक्रोनाइज्ड' कीवर्ड का उपयोग, एटॉमिकएक्सएक्सएक्सएक्स वैरिएबल आदि का उपयोग) के बिना थ्रेड से मुख्य थ्रेड तक 'शेयर्ड वीयर' के नए मूल्य को 'ट्रांसफर' करने की आवश्यकता नहीं है।


5

सीधे शब्दों में कहें: पूरा
t1.join()होने के बाद रिटर्न t1
यह थ्रेड के लिए कुछ भी नहीं करता है t1, सिवाय इसके खत्म होने का इंतजार करने के।
स्वाभाविक रूप से, कोड का पालन रिटर्न के t1.join()बाद ही किया जाएगा t1.join()


1
t1.join () रिटर्न +1
mohsen.nour

3

Join पर oracle के प्रलेखन पृष्ठ से

joinविधि एक धागा एक और पूरा करने के लिए प्रतीक्षा करने के लिए अनुमति देता है।

यदि t1 एक ऐसी Threadवस्तु है जिसका धागा वर्तमान में निष्पादित हो रहा है,

t1.join() : causes the current thread to pause execution until t1's thread terminates.

यदि t2 एक ऐसी Threadवस्तु है जिसका धागा वर्तमान में निष्पादित हो रहा है,

t2.join(); causes the current thread to pause execution until t2's thread terminates.

joinएपीआई निम्न स्तर का एपीआई है, जिसे जावा के पुराने संस्करणों में पेश किया गया है। समसामयिक मोर्चे पर समय की अवधि (विशेषकर jdk 1.5 रिलीज के साथ) में बहुत सारी चीजें बदल दी गई हैं।

आप java.util.concurrent API से इसे प्राप्त कर सकते हैं। कुछ उदाहरण हैं

  1. पर invokeAll का उपयोग करनाExecutorService
  2. CountDownLatch का उपयोग करना
  3. ForkJoinPool या newWorkStealingPool का उपयोग करना Executors(जावा 8 से)

संबंधित एसई प्रश्नों का संदर्भ लें:

तब तक प्रतीक्षा करें जब तक कि सभी धागे जावा में अपना काम खत्म न कर दें


1

मेरे लिए, Join () व्यवहार हमेशा भ्रमित था क्योंकि मैं यह याद रखने की कोशिश कर रहा था कि कौन किसके लिए इंतजार करेगा। इसे इस तरह याद रखने की कोशिश मत करो।

नीचे, यह शुद्ध प्रतीक्षा है () और सूचना () तंत्र।

हम सभी जानते हैं कि, जब हम किसी वस्तु (t1) पर प्रतीक्षा () कहते हैं, तो कॉलिंग ऑब्जेक्ट (मुख्य) को प्रतीक्षा कक्ष (अवरुद्ध अवस्था) में भेजा जाता है।

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

अधिसूचना प्राप्त करने के बाद, मुख्य प्रतीक्षा कक्ष से बाहर आता है और इसे निष्पादित करता है।


0

आशा करता हूँ की ये काम करेगा!

package join;

public class ThreadJoinApp {

    Thread th = new Thread("Thread 1") {
        public void run() {
            System.out.println("Current thread execution - " + Thread.currentThread().getName());
            for (int i = 0; i < 10; i++) {
                System.out.println("Current thread execution - " + Thread.currentThread().getName() + " at index - " + i);
            }
        }
    };

    Thread th2 = new Thread("Thread 2") {
        public void run() {
            System.out.println("Current thread execution - " + Thread.currentThread().getName());

            //Thread 2 waits until the thread 1 successfully completes.
            try {
            th.join();
            } catch( InterruptedException ex) {
                System.out.println("Exception has been caught");
            }

            for (int i = 0; i < 10; i++) {
                System.out.println("Current thread execution - " + Thread.currentThread().getName() + " at index - " + i);
            }
        }
    };

    public static void main(String[] args) {
        ThreadJoinApp threadJoinApp = new ThreadJoinApp();
        threadJoinApp.th.start();
        threadJoinApp.th2.start();
    }

    //Happy coding -- Parthasarathy S
}

-3

मान लीजिए कि हमारा मुख्य धागा थ्रेड्स टी 1 और टी 2 शुरू होता है। अब, जब t1.join () को कॉल किया जाता है, तो मुख्य थ्रेड तब तक सस्पेंड होता है जब तक कि थ्रेड t1 मर जाता है और फिर खुद को फिर से शुरू कर देता है। इसी तरह, जब t2.join () निष्पादित होता है, तो मुख्य धागा स्वयं को फिर से निलंबित कर देता है जब तक कि धागा t2 मर जाता है और फिर शुरू हो जाता है।

तो, यह है कि यह कैसे काम करता है।

इसके अलावा, जबकि लूप की वास्तव में यहां जरूरत नहीं थी।

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