मल्टीथ्रेडिंग द्वारा हल की गई समस्याएं
मल्टीथ्रेडिंग का आविष्कार वास्तव में दो महत्वपूर्ण उद्देश्यों को प्राप्त करने के लिए किया गया था:-
एक ही समय में कई काम करें।
उपरोक्त उदाहरण में, अलग-अलग थ्रेड्स (परिवार के सदस्यों) ने समानांतर में कई क्रियाएं कीं: उन्होंने बर्तन धोए, स्टोर में गए और चीजों को पैक किया।
हम प्रोग्रामिंग से अधिक निकटता से संबंधित एक उदाहरण प्रस्तुत कर सकते हैं। मान लीजिए कि आपके पास यूजर इंटरफेस वाला एक प्रोग्राम है। जब आप प्रोग्राम में 'जारी रखें' पर क्लिक करते हैं, तो कुछ गणनाएँ होनी चाहिए और उपयोगकर्ता को निम्न स्क्रीन दिखाई देनी चाहिए। यदि ये क्रियाएं क्रमिक रूप से की जाती हैं, तो उपयोगकर्ता द्वारा 'जारी रखें' बटन पर क्लिक करने के बाद ही प्रोग्राम हैंग हो जाएगा। उपयोगकर्ता स्क्रीन को 'जारी रखें' बटन स्क्रीन के साथ तब तक देखेगा जब तक कि प्रोग्राम सभी आंतरिक गणना नहीं करता है और उस हिस्से तक पहुंच जाता है जहां उपयोगकर्ता इंटरफ़ेस को ताज़ा किया जाता है।
ठीक है, मुझे लगता है कि हम कुछ मिनट प्रतीक्षा करेंगे!
या हम अपने कार्यक्रम पर फिर से काम कर सकते हैं, या, जैसा कि प्रोग्रामर कहते हैं, इसे 'समानांतर' करें। आइए एक धागे पर अपनी गणना करते हैं और दूसरे पर यूजर इंटरफेस बनाते हैं। ऐसा करने के लिए अधिकांश कंप्यूटरों के पास पर्याप्त संसाधन होते हैं। यदि हम यह रास्ता अपनाते हैं, तो प्रोग्राम फ्रीज नहीं होगा और उपयोगकर्ता अंदर क्या हो रहा है, इसकी चिंता किए बिना स्क्रीन के बीच सुचारू रूप से चलेगा। एक दूसरे के साथ हस्तक्षेप नहीं करता :)
-
अधिक तेज़ी से गणना करें।
यहाँ सब कुछ बहुत आसान है। यदि हमारे प्रोसेसर में कई कोर हैं, और अधिकांश प्रोसेसर आज हैं, तो कई कोर हमारे कार्यों की सूची को समानांतर में संभाल सकते हैं। जाहिर है, अगर हमें 1000 कार्य करने की आवश्यकता है और प्रत्येक को एक सेकंड लगता है, तो एक कोर 1000 सेकंड में सूची को पूरा कर सकता है, 500 सेकंड में दो कोर, 333 सेकंड से थोड़ा अधिक में तीन, आदि।
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 है
मल्टीथ्रेडिंग द्वारा बनाई गई समस्याएं
पुस्तकों के साथ हमारे उदाहरण में, आपने देखा कि मल्टीथ्रेडिंग बहुत महत्वपूर्ण कार्यों को हल करती है और हमारे प्रोग्राम को तेज़ बना सकती है। अक्सर कई गुना तेज। लेकिन मल्टीथ्रेडिंग को एक कठिन विषय माना जाता है। दरअसल, अगर गलत तरीके से इस्तेमाल किया जाए तो यह उन्हें हल करने के बजाय समस्याएं पैदा करता है। जब मैं कहता हूं 'समस्याएं पैदा करता है', तो मेरा मतलब किसी अमूर्त अर्थ में नहीं है। दो विशिष्ट समस्याएं हैं जो मल्टीथ्रेडिंग बना सकती हैं: गतिरोध और दौड़ की स्थिति। गतिरोध एक ऐसी स्थिति है जहां कई थ्रेड्स एक दूसरे के पास संसाधनों की प्रतीक्षा कर रहे हैं, और उनमें से कोई भी चलना जारी नहीं रख सकता है। इसके बारे में हम बाद के पाठों में और बात करेंगे। निम्नलिखित उदाहरण अभी के लिए पर्याप्त होगा:
- थ्रेड -1 ऑब्जेक्ट -1 के साथ इंटरैक्ट करना बंद कर देता है और जैसे ही थ्रेड -2 ऑब्जेक्ट -2 के साथ इंटरैक्ट करना बंद कर देता है और ऑब्जेक्ट -1 पर स्विच हो जाता है, ऑब्जेक्ट -2 पर स्विच हो जाता है।
- थ्रेड-2 ऑब्जेक्ट-2 के साथ इंटरैक्ट करना बंद कर देता है और जैसे ही थ्रेड-1 ऑब्जेक्ट-1 के साथ इंटरैक्ट करना बंद कर देता है और ऑब्जेक्ट-2 पर स्विच हो जाता है, ऑब्जेक्ट-1 पर स्विच हो जाता है।
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 क्या यह कॉमेडी रूटीन है? :) और सभी क्योंकि हमारे कार्यक्रम का काम थ्रेड्स के निष्पादन क्रम पर निर्भर करता है। आवश्यक अनुक्रम के थोड़े से उल्लंघन को देखते हुए, हमारी रसोई नरक में बदल जाती है, और एक पागल रोबोट इसके चारों ओर सब कुछ नष्ट कर देता है। मल्टीथ्रेडेड प्रोग्रामिंग में यह भी एक आम समस्या है। आप इसके बारे में एक से अधिक बार सुनेंगे। इस पाठ के समापन में, मैं मल्टीथ्रेडिंग के बारे में एक किताब की सिफारिश करना चाहूंगा। 
GO TO FULL VERSION