एक ही समय में "ठीक" पर दो धागे कैसे शुरू करें


91

धागे एक ही विभाजन दूसरे पर शुरू होना चाहिए। मैं समझता हूं, यदि आप करते हैं thread1.start(), तो अगले निष्पादन से पहले कुछ मिलीसेकंड लगेगा thread2.start()

क्या यह भी संभव है या असंभव है?


2
स्प्लिट सेकंड, गीगाहर्ट्ज की गति पर बहुत लंबा समय है।
निकोलाई Fetissov

30
इतनी तीव्रता से नीचे उतरने की जरूरत नहीं है। हर कोई थ्रेडिंग से संबंधित नॉडटर्मिनिज़्म को नहीं समझता है, और हम सभी को कहीं न कहीं शुरुआत करनी होगी।
माइकल पेट्रोत्ता

7
चढ़ाव को न समझें। धागे के बीच सिंक्रनाइज़ करना एक बहुत ही सामान्य आवश्यकता है। हाँ, जावा में आप उन्हें बिल्कुल समानांतर में निष्पादित नहीं कर सकते हैं (जो, अन्य प्लेटफ़ॉर्म पर एक बहुत ही मान्य आवश्यकता btw हो सकती है), लेकिन समय-समय पर यह बहुत आम है कि आपको उनकी कार्रवाई को सिंक्रनाइज़ करने की आवश्यकता है। इसलिए jdk के पास ऐसा करने के लिए कक्षाएं हैं। हो सकता है कि
शब्दांकन

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

2
@javaguy - एक "चाल" सवाल नहीं। बल्कि यह देखने के लिए एक प्रश्न चुना जाता है कि आप बहु-थ्रेडेड प्रोग्रामिंग को सामान्य रूप से कितनी अच्छी तरह समझते हैं ... साथ ही जावा मामले में भी।
स्टीफन सी।

जवाबों:


135

थ्रेड्स को ठीक उसी समय शुरू करने के लिए (कम से कम जितना संभव हो उतना अच्छा), आप साइक्लिक बैरियर का उपयोग कर सकते हैं :

// We want to start just 2 threads at the same time, but let's control that 
// timing from the main thread. That's why we have 3 "parties" instead of 2.
final CyclicBarrier gate = new CyclicBarrier(3);

Thread t1 = new Thread(){
    public void run(){
        gate.await();
        //do stuff    
    }};
Thread t2 = new Thread(){
    public void run(){
        gate.await();
        //do stuff    
    }};

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

// At this point, t1 and t2 are blocking on the gate. 
// Since we gave "3" as the argument, gate is not opened yet.
// Now if we block on the gate from the main thread, it will open
// and all threads will start to do stuff!

gate.await();
System.out.println("all threads started");

यह एक होना जरूरी नहीं है CyclicBarrier, आप एक CountDownLatchया यहां तक ​​कि एक ताला भी इस्तेमाल कर सकते हैं ।

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

अन्य प्लेटफार्मों पर, थ्रेड शुरू करना वास्तव में एक बहुत ही वैध आवश्यकता है।


5
+1 अच्छी सोच;; हालांकि बेशक यह धागे को वास्तविक समय में ठीक उसी समय शुरू नहीं करता है (कम से कम सिंगल-कोर चिप पर नहीं, और मल्टी-कोर चिप पर भी गारंटी नहीं है), लेकिन मैं बेहतर करने के लिए कोई भी तरीका नहीं सोच सकता।
डेविड जेड

क्या यह हुक पर्यावरण विशिष्ट प्रतीक्षा हैंडल में होगा?
चोसपंडियन

@ChaosPandion: विस्तृत करने के लिए देखभाल?
सांता

@ संता - उदाहरण के लिए Win32 API विभिन्न प्राइमेटिव प्रदान करता है। जब आप कॉल करते हैं तो एक उपयोगी प्रकार मैन्युअल रीसेट घटना होती है CreateEventmsdn.microsoft.com/en-us/library/ms686364%28VS.85%29.aspx
ChaosPandion

1
@ ज़ेवी - खैर, जो भी हो, यह जवाब है जो मैंने पोस्ट किया होगा मैं एक जावा गुरु था।
चोसपंडियन जूल

15

यह संभव नहीं है, कम से कम सिंगल कोर कंप्यूटर पर। लेकिन आप ऐसा क्यों चाहते हैं? यहां तक ​​कि अगर आप एक ही सेकंड में दो धागे शुरू करने में सक्षम थे, तो भी वे अलग-अलग प्रगति करेंगे क्योंकि शेड्यूलिंग आपके नियंत्रण में नहीं है।

संपादित करें: (कुछ टिप्पणियों के जवाब में) यह कई धागे की स्थिति या प्रगति को सिंक्रनाइज़ करने के लिए एक पूरी तरह से वैध आवश्यकता है और CyclicBarrierएक महान उपकरण है। मैंने इस सवाल का जवाब दिया कि क्या एक ही समय में कई थ्रेड शुरू करना संभव है । CyclicBarrierगारंटी देंगे कि थ्रेड्स वांछित स्थिति में होने पर आगे बढ़ते हैं लेकिन यह गारंटी नहीं देता है कि वे ठीक उसी समय शुरू या फिर से शुरू करेंगे , हालांकि यह बहुत करीब हो सकता है। प्रश्न में सिंक्रोनाइज़ेशन आवश्यकताओं का कोई उल्लेख नहीं है।


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

विचार यह है कि यह गलत-अध्यक्षता वाला दृष्टिकोण है और किसी भी मुश्किल-वास्तविक-वास्तविक वातावरण में आवश्यक नहीं होना चाहिए, न कि यह "बहुत करीब" है।
निकोलाई Fetissov

1
यह भी असंभव है क्योंकि जावा थ्रेड शेड्यूलिंग आपको मिलीसेकंड सटीकता नहीं देता है।
स्टीफन सी।

1
@ ज़ेवी - आप शायद एक बेकार मशीन पर ज्यादातर समय "लानत पास" प्राप्त कर सकते हैं। लेकिन अगर आपको हर समय इसकी आवश्यकता है, तो आपको ओएस में हार्ड रियलटाइम समर्थन वाली मशीन पर, सी जैसी भाषा में प्रोग्राम करने की आवश्यकता है। इस बात पर भी विचार करें कि जेवीएम "स्प्लिट सेकंड" पर एक पूर्ण जीसी चल रहा हो सकता है जिसे आप अपने धागे को शुरू करना चाहते हैं।
स्टीफन सी।

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

14

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

import java.util.concurrent.CountDownLatch;


public class ThreadExample
{
    public static void main(String[] args) 
    {
        CountDownLatch latch = new CountDownLatch(1);
        MyThread t1 = new MyThread(latch);
        MyThread t2 = new MyThread(latch);
        new Thread(t1).start();
        new Thread(t2).start();
        //Do whatever you want
        latch.countDown();          //This will inform all the threads to start
        //Continue to do whatever
    }
}

class MyThread implements Runnable
{
    CountDownLatch latch;
    public MyThread(CountDownLatch latch) 
    {
        this.latch = latch;
    }
    @Override
    public void run() 
    {
        try 
        {
            latch.await();          //The thread keeps waiting till it is informed
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //Do the actual thing
    }
}

यह उत्तर कोड उदाहरण में कम बॉयलर से लाभ उठा सकता है।
user2418306

6
  1. जैसा कि मैं इसे समझता हूं, जेवीएम ज्यादातर इस सामान को ऑपरेटिंग सिस्टम को सौंपता है। तो जवाब होगा ओएस-विशिष्ट।
  2. यह एकल-प्रोसेसर मशीनों पर स्पष्ट रूप से असंभव है।
  3. यह एक बहु-प्रोसेसर मशीन के संबंध में अधिक जटिल है। युगपतता की सापेक्षता के अनुसार , "यह एक पूर्ण अर्थ में कहना असंभव है कि क्या दो घटनाएं एक ही समय में होती हैं यदि उन घटनाओं को अंतरिक्ष में अलग किया जाता है।" कोई फर्क नहीं पड़ता कि आपके प्रोसेसर कितने करीब हैं, वे अंतरिक्ष में अलग हो गए हैं।
    1. यदि आप एक साथ सापेक्षता को स्वीकार कर सकते हैं, तो शायद यह आसान है कि अन्य प्रतिक्रियाओं में चर्चा की गई तकनीकों का उपयोग करके इसे अनुकरण करें।

1
... और यहां तक ​​कि अगर हम एक साथ शुरू करते हैं, तो प्रत्येक थ्रेड की अपनी समयरेखा होती है, सभी समवर्ती होते हैं , लेकिन जरूरी नहीं कि समानांतर हो, इसलिए जो भी व्यक्ति धागे की एक साथता के बारे में मानता है (विल) अगले नैनोसेकंड (जो भी) में शून्य हो सकता है समयरेखा) ...
होल्गर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.