CodeGym /Java Blog /अनियमित /जावा में मल्टीथ्रेडिंग
John Squirrels
स्तर 41
San Francisco

जावा में मल्टीथ्रेडिंग

अनियमित ग्रुप में प्रकाशित
नमस्ते! सबसे पहले, बधाई हो: आप जावा में मल्टीथ्रेडिंग के विषय पर पहुंच गए हैं! यह एक गंभीर उपलब्धि है — आपने एक लंबा सफर तय किया है। लेकिन अपने आप को तैयार करें: यह पाठ्यक्रम के सबसे कठिन विषयों में से एक है। और ऐसा नहीं है कि हम यहाँ जटिल कक्षाओं या बहुत सारी विधियों का उपयोग कर रहे हैं: वास्तव में, हम बीस से कम का उपयोग करेंगे। यह अधिक है कि आपको अपने सोचने के तरीके को थोड़ा बदलने की आवश्यकता होगी। पहले, आपके कार्यक्रमों को क्रमिक रूप से क्रियान्वित किया गया है। कोड की कुछ पंक्तियाँ दूसरों के बाद आईं, कुछ विधियाँ दूसरों के बाद आईं, और सब कुछ मूल रूप से स्पष्ट था। सबसे पहले, हमने कुछ गणना की, फिर कंसोल पर परिणाम प्रदर्शित किया और फिर कार्यक्रम समाप्त हो गया। मल्टीथ्रेडिंग को समझने के लिए समानता के संदर्भ में सोचना बेहतर है। आइए कुछ बहुत ही सरल से शुरू करें: ) कल्पना कीजिए कि आपका परिवार एक घर से दूसरे घर में जा रहा है। अपनी सभी पुस्तकों को इकट्ठा करना इस कदम का एक महत्वपूर्ण हिस्सा होगा। आपने बहुत सारी पुस्तकें जमा कर ली हैं, और आपको उन्हें बक्सों में रखने की आवश्यकता है। वर्तमान में, केवल आप ही उपलब्ध हैं। माँ खाना बना रही है, भाई कपड़े बाँध रहा है, और बहन दुकान पर चली गई। अकेले, आप किसी तरह प्रबंधन कर सकते हैं। देर-सवेर आप स्वयं कार्य पूरा कर लेंगे, लेकिन इसमें काफी समय लगेगा। हालाँकि, आपकी बहन 20 मिनट में स्टोर से वापस आ जाएगी, और उसके पास और कुछ करने को नहीं है। तो वह आपसे जुड़ सकती है। कार्य नहीं बदला है: पुस्तकों को बक्सों में रखें। लेकिन यह दोगुनी तेजी से किया जा रहा है। क्यों? क्योंकि काम समानांतर चल रहा है। दो अलग-अलग 'धागे' (आप और आपकी बहन) एक साथ एक ही कार्य कर रहे हैं। और अगर कुछ नहीं बदला, तब उस स्थिति की तुलना में समय का बहुत बड़ा अंतर होगा जहां आप सब कुछ स्वयं करते हैं। अगर भाई अपना काम जल्द पूरा कर लेता है, तो वह आपकी मदद कर सकता है और चीजें और भी तेजी से आगे बढ़ेंगी।

मल्टीथ्रेडिंग द्वारा हल की गई समस्याएं

मल्टीथ्रेडिंग का आविष्कार वास्तव में दो महत्वपूर्ण उद्देश्यों को प्राप्त करने के लिए किया गया था:
  1. एक ही समय में कई काम करें।

    उपरोक्त उदाहरण में, अलग-अलग थ्रेड्स (परिवार के सदस्यों) ने समानांतर में कई क्रियाएं कीं: उन्होंने बर्तन धोए, स्टोर में गए और चीजों को पैक किया।

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

    ठीक है, मुझे लगता है कि हम कुछ मिनट प्रतीक्षा करेंगे!

    जावा में मल्टीथ्रेडिंग: यह क्या है, इसके फायदे और आम नुकसान - 3

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

  2. अधिक तेज़ी से गणना करें।

    यहाँ सब कुछ बहुत आसान है। यदि हमारे प्रोसेसर में कई कोर हैं, और अधिकांश प्रोसेसर आज हैं, तो कई कोर हमारे कार्यों की सूची को समानांतर में संभाल सकते हैं। जाहिर है, अगर हमें 1000 कार्य करने की आवश्यकता है और प्रत्येक को एक सेकंड लगता है, तो एक कोर 1000 सेकंड में सूची को पूरा कर सकता है, 500 सेकंड में दो कोर, 333 सेकंड से थोड़ा अधिक में तीन, आदि।

लेकिन जैसा कि आप इस पाठ में पहले ही पढ़ चुके हैं, आज के सिस्टम बहुत स्मार्ट हैं, और यहां तक ​​कि एक कंप्यूटिंग कोर पर समानांतरता, या छद्म-समानांतरवाद प्राप्त करने में सक्षम हैं, जहां कार्य वैकल्पिक रूप से किए जाते हैं। आइए सामान्यताओं को बारीकियों पर ले जाएं और जावा मल्टीथ्रेडिंग लाइब्रेरी में सबसे महत्वपूर्ण वर्ग - java.lang.Thread को जानें। कड़ाई से बोलना, जावा थ्रेड्स को थ्रेड क्लास के उदाहरणों द्वारा दर्शाया गया है। इसका मतलब है कि 10 धागे बनाने और चलाने के लिए आपको इस वर्ग के 10 उदाहरण चाहिए। आइए सबसे सरल उदाहरण लिखें:

public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("I'm Thread! My name is " + getName());
   }
}
धागे बनाने और चलाने के लिए, हमें एक वर्ग बनाने की जरूरत है, इसे java.lang इनहेरिट करें । थ्रेड क्लास, और इसके रन () विधि को ओवरराइड करें। वह अंतिम आवश्यकता बहुत महत्वपूर्ण है। यह रन () विधि में है कि हम अपने थ्रेड को निष्पादित करने के लिए तर्क को परिभाषित करते हैं। अब, यदि हम MyFirstThread का एक उदाहरण बनाते और चलाते हैं , तो रन () विधि एक नाम के साथ एक पंक्ति प्रदर्शित करेगी: getName () विधि थ्रेड के 'सिस्टम' नाम को प्रदर्शित करती है, जो स्वचालित रूप से असाइन की जाती है। लेकिन हम अस्थायी रूप से क्यों बोल रहे हैं? आइए एक बनाएं और पता करें!

public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {

           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
कंसोल आउटपुट: मैं थ्रेड हूँ! मेरा नाम थ्रेड-2 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-1 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-0 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-3 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-6 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-7 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-4 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-5 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-9 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-8 है आइए 10 थ्रेड्स ( MyFirstThread ऑब्जेक्ट्स, जो थ्रेड इनहेरिट करते हैं ) बनाएं और प्रत्येक ऑब्जेक्ट पर स्टार्ट () विधि को कॉल करके उन्हें शुरू करें। प्रारंभ () विधि को कॉल करने के बाद , रन () विधि में तर्क निष्पादित किया जाता है। नोट: धागे के नाम क्रम में नहीं हैं। यह अजीब है कि वे क्रमिक रूप से नहीं थे:, थ्रेड-1 , थ्रेड-2 , और इसी तरह? जैसा कि होता है, यह एक ऐसे समय का उदाहरण है जब 'अनुक्रमिक' सोच फिट नहीं होती है। समस्या यह है कि हमने केवल 10 सूत्र बनाने और चलाने के लिए आदेश प्रदान किए हैं। थ्रेड अनुसूचक, एक विशेष ऑपरेटिंग सिस्टम तंत्र, उनके निष्पादन क्रम को तय करता है। इसकी सटीक डिजाइन और निर्णय लेने की रणनीति एक गहन चर्चा का विषय है जिस पर हम अभी चर्चा नहीं करेंगे। याद रखने वाली मुख्य बात यह है कि प्रोग्रामर थ्रेड्स के निष्पादन क्रम को नियंत्रित नहीं कर सकता है। स्थिति की गंभीरता को समझने के लिए ऊपर दिए गए उदाहरण में main() मेथड को कुछ और बार चलाने का प्रयास करें। दूसरे रन पर कंसोल आउटपुट: मैं थ्रेड हूँ! मेरा नाम थ्रेड-0 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-4 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-3 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-2 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-1 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-5 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-6 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-8 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-9 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-7 कंसोल आउटपुट तीसरे रन से है: मैं थ्रेड हूं! मेरा नाम थ्रेड-0 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-3 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-1 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-2 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-6 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-4 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-9 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-5 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-7 है मैं थ्रेड हूँ! मेरा नाम थ्रेड-8 है

मल्टीथ्रेडिंग द्वारा बनाई गई समस्याएं

पुस्तकों के साथ हमारे उदाहरण में, आपने देखा कि मल्टीथ्रेडिंग बहुत महत्वपूर्ण कार्यों को हल करती है और हमारे प्रोग्राम को तेज़ बना सकती है। अक्सर कई गुना तेज। लेकिन मल्टीथ्रेडिंग को एक कठिन विषय माना जाता है। दरअसल, अगर गलत तरीके से इस्तेमाल किया जाए तो यह उन्हें हल करने के बजाय समस्याएं पैदा करता है। जब मैं कहता हूं 'समस्याएं पैदा करता है', तो मेरा मतलब किसी अमूर्त अर्थ में नहीं है। दो विशिष्ट समस्याएं हैं जो मल्टीथ्रेडिंग बना सकती हैं: गतिरोध और दौड़ की स्थिति। गतिरोध एक ऐसी स्थिति है जहां कई थ्रेड्स एक दूसरे के पास संसाधनों की प्रतीक्षा कर रहे हैं, और उनमें से कोई भी चलना जारी नहीं रख सकता है। इसके बारे में हम बाद के पाठों में और बात करेंगे। निम्नलिखित उदाहरण अभी के लिए पर्याप्त होगा: जावा में मल्टीथ्रेडिंग: यह क्या है, इसके फायदे और आम नुकसान - 4कल्पना करें कि थ्रेड-1 किसी ऑब्जेक्ट-1 के साथ इंटरैक्ट करता है, और थ्रेड-2 ऑब्जेक्ट-2 के साथ इंटरैक्ट करता है। इसके अलावा, कार्यक्रम लिखा है ताकि:
  1. थ्रेड -1 ऑब्जेक्ट -1 के साथ इंटरैक्ट करना बंद कर देता है और जैसे ही थ्रेड -2 ऑब्जेक्ट -2 के साथ इंटरैक्ट करना बंद कर देता है और ऑब्जेक्ट -1 पर स्विच हो जाता है, ऑब्जेक्ट -2 पर स्विच हो जाता है।
  2. थ्रेड-2 ऑब्जेक्ट-2 के साथ इंटरैक्ट करना बंद कर देता है और जैसे ही थ्रेड-1 ऑब्जेक्ट-1 के साथ इंटरैक्ट करना बंद कर देता है और ऑब्जेक्ट-2 पर स्विच हो जाता है, ऑब्जेक्ट-1 पर स्विच हो जाता है।
मल्टीथ्रेडिंग की गहरी समझ के बिना भी आप आसानी से देख सकते हैं कि कुछ भी नहीं होगा। धागे कभी भी स्थान नहीं बदलेंगे और हमेशा के लिए एक दूसरे की प्रतीक्षा करेंगे। त्रुटि स्पष्ट प्रतीत होती है, लेकिन वास्तव में ऐसा नहीं है। इसे आप किसी प्रोग्राम में आसानी से कर सकते हैं। हम उन कोड के उदाहरणों पर विचार करेंगे जो बाद के पाठों में डेडलॉक का कारण बनते हैं। वैसे, Quora के पास वास्तविक जीवन का एक बेहतरीन उदाहरण है जो बताता है कि डेडलॉक क्या होता हैहै। 'भारत के कुछ राज्यों में, जब तक आप एक पंजीकृत किसान नहीं हैं, वे आपको कृषि भूमि नहीं बेचेंगे। हालांकि, यदि आपके पास कृषि भूमि नहीं है तो वे आपको एक किसान के रूप में पंजीकृत नहीं करेंगे। महान! हम क्या कह सकते हैं ?! :) अब दौड़ की स्थिति के बारे में बात करते हैं। दौड़ की स्थिति एक मल्टीथ्रेडेड सिस्टम या एप्लिकेशन में एक डिज़ाइन त्रुटि है, जहां सिस्टम या एप्लिकेशन का संचालन उस क्रम पर निर्भर करता है जिसमें कोड के कुछ हिस्सों को निष्पादित किया जाता है। याद रखें, हमारा उदाहरण जहां हमने धागे शुरू किए:

public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("Thread executed: " + getName());
   }
}

public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {

           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
अब कल्पना कीजिए कि खाना पकाने वाले रोबोट को चलाने के लिए कार्यक्रम जिम्मेदार है! थ्रेड-0 फ्रिज से अंडे निकालता है। थ्रेड-1 चूल्हे को चालू करता है। थ्रेड-2 एक पैन लेकर उसे स्टोव पर रख देता है। थ्रेड -3 चूल्हा जलाता है। धागा-4 कढ़ाई में तेल डालेगा। धागा-5 अण्डों को तोड़कर पैन में डाल देता है। थ्रेड-6 अंडे के छिलकों को कूड़ेदान में फेंक देता है। थ्रेड-7 पके हुए अंडों को बर्नर से निकालता है। धागा-8 पके हुए अण्डों को एक प्लेट में रखते हैं। सूत्र-9 बर्तन धोता है। हमारे कार्यक्रम के परिणामों को देखें: थ्रेड निष्पादित: थ्रेड-0 थ्रेड निष्पादित: थ्रेड-2 थ्रेड निष्पादित थ्रेड-1 थ्रेड निष्पादित: थ्रेड-4 थ्रेड निष्पादित: थ्रेड-9 थ्रेड निष्पादित: थ्रेड-5 थ्रेड निष्पादित: थ्रेड-8 थ्रेड निष्पादित: थ्रेड-7 थ्रेड निष्पादित: थ्रेड-3 क्या यह कॉमेडी रूटीन है? :) और सभी क्योंकि हमारे कार्यक्रम का काम थ्रेड्स के निष्पादन क्रम पर निर्भर करता है। आवश्यक अनुक्रम के थोड़े से उल्लंघन को देखते हुए, हमारी रसोई नरक में बदल जाती है, और एक पागल रोबोट इसके चारों ओर सब कुछ नष्ट कर देता है। मल्टीथ्रेडेड प्रोग्रामिंग में यह भी एक आम समस्या है। आप इसके बारे में एक से अधिक बार सुनेंगे। इस पाठ के समापन में, मैं मल्टीथ्रेडिंग के बारे में एक किताब की सिफारिश करना चाहूंगा। जावा में मल्टीथ्रेडिंग: यह क्या है, इसके फायदे और आम नुकसान - 6'जावा कॉन्करेंसी इन प्रैक्टिस' 2006 में लिखी गई थी, लेकिन इसने अपनी प्रासंगिकता नहीं खोई है। यह मल्टीथ्रेडेड जावा प्रोग्रामिंग के लिए समर्पित है - मूल से लेकर सबसे आम गलतियों और एंटीपैटर्न तक। यदि आप किसी दिन मल्टीथ्रेडिंग गुरु बनने का निर्णय लेते हैं, तो यह पुस्तक अवश्य पढ़ी जानी चाहिए। अगले पाठों में मिलते हैं! :)
टिप्पणियां
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION