मल्टीथ्रेडिंगद्वारे समस्या सोडवल्या जातात
मल्टीथ्रेडिंगचा शोध प्रत्यक्षात दोन महत्त्वाची उद्दिष्टे साध्य करण्यासाठी लावला गेला:-
एकाच वेळी अनेक गोष्टी करा.
वरील उदाहरणात, वेगवेगळ्या थ्रेड्सने (कुटुंबातील सदस्यांनी) समांतरपणे अनेक क्रिया केल्या: त्यांनी भांडी धुतली, दुकानात गेली आणि वस्तू पॅक केल्या.
आम्ही प्रोग्रामिंगशी संबंधित एक उदाहरण देऊ शकतो. समजा तुमच्याकडे यूजर इंटरफेस असलेला प्रोग्राम आहे. जेव्हा तुम्ही प्रोग्राममध्ये 'Continue' वर क्लिक करता, तेव्हा काही गणना व्हायला हवी आणि वापरकर्त्याला खालील स्क्रीन दिसली पाहिजे. जर या क्रिया क्रमाक्रमाने केल्या गेल्या असतील, तर वापरकर्त्याने 'सुरू ठेवा' बटणावर क्लिक केल्यानंतर प्रोग्राम हँग होईल. जोपर्यंत प्रोग्राम सर्व अंतर्गत आकडेमोड करत नाही आणि वापरकर्ता इंटरफेस रीफ्रेश केला आहे त्या भागापर्यंत पोहोचेपर्यंत वापरकर्त्याला 'सुरू ठेवा' बटण स्क्रीनसह स्क्रीन दिसेल.
बरं, मला वाटतं आम्ही काही मिनिटे थांबू!
किंवा आम्ही आमच्या प्रोग्रामची पुनर्रचना करू शकतो, किंवा प्रोग्रामर म्हणतात त्याप्रमाणे, त्यास 'समांतर' करू शकतो. चला एका थ्रेडवर आपली गणना करू आणि दुसर्या थ्रेडवर वापरकर्ता इंटरफेस काढू. बहुतेक संगणकांकडे हे करण्यासाठी पुरेशी संसाधने आहेत. जर आपण हा मार्ग स्वीकारला, तर प्रोग्राम गोठणार नाही आणि वापरकर्ता आत काय घडत आहे याची काळजी न करता स्क्रीन दरम्यान सहजतेने फिरेल. एक दुसऱ्यामध्ये हस्तक्षेप करत नाही :)
-
गणना अधिक जलद करा.
येथे सर्व काही खूप सोपे आहे. जर आमच्या प्रोसेसरमध्ये एकाधिक कोर असतील आणि आज बहुतेक प्रोसेसर करतात, तर अनेक कोर आमच्या कार्यांची सूची समांतरपणे हाताळू शकतात. अर्थात, जर आम्हाला 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 चे उदाहरण तयार केले आणि चालवले तर , run() पद्धत नावासह एक ओळ प्रदर्शित करेल: 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 आहे मी थ्रेड आहे! My name is Thread-8 चला 10 थ्रेड्स ( MyFirstThread ऑब्जेक्ट्स, जे थ्रेड इनहेरिट करतात ) बनवू आणि प्रत्येक ऑब्जेक्टवर start() मेथड कॉल करून सुरू करू. start() मेथडला कॉल केल्यानंतर , run() मेथडमधील लॉजिक कार्यान्वित केले जाते. टीप: धाग्याची नावे क्रमाने नाहीत. हे विचित्र आहे की ते अनुक्रमे नव्हते:, थ्रेड -1 , थ्रेड -2 , आणि असेच? जसे घडते तसे, हे अशा वेळेचे उदाहरण आहे जेव्हा 'अनुक्रमिक' विचार जुळत नाही. समस्या अशी आहे की आम्ही फक्त 10 थ्रेड्स तयार करण्यासाठी आणि चालवण्यासाठी कमांड प्रदान केल्या आहेत. थ्रेड शेड्यूलर, एक विशेष कार्यप्रणाली यंत्रणा, त्यांच्या अंमलबजावणीचा क्रम ठरवते. त्याची नेमकी रचना आणि निर्णय घेण्याची रणनीती हे सखोल चर्चेचे विषय आहेत ज्यात आम्ही आत्ता डुबकी मारणार नाही. लक्षात ठेवण्याची मुख्य गोष्ट अशी आहे की प्रोग्रामर थ्रेड्सच्या अंमलबजावणीचा क्रम नियंत्रित करू शकत नाही. परिस्थितीचे गांभीर्य समजून घेण्यासाठी, वरील उदाहरणातील main() पद्धत आणखी काही वेळा चालवण्याचा प्रयत्न करा. दुसऱ्या रनवर कन्सोल आउटपुट: मी थ्रेड आहे! माझे नाव थ्रेड आहे-0 मी थ्रेड आहे! माझे नाव थ्रेड आहे -4 मी थ्रेड आहे! माझे नाव थ्रेड -3 आहे मी थ्रेड आहे! माझे नाव थ्रेड आहे -2 मी धागा आहे! माझे नाव थ्रेड-1 मी धागा आहे! माझे नाव थ्रेड-5 आहे मी थ्रेड आहे! माझे नाव थ्रेड -6 आहे मी थ्रेड आहे! माझे नाव थ्रेड-8 आहे मी थ्रेड आहे! माझे नाव थ्रेड-9 आहे मी थ्रेड आहे! माझे नाव आहे थ्रेड-७ कन्सोल आउटपुट तिसऱ्या रनमधून: मी थ्रेड आहे! माझे नाव थ्रेड आहे-0 मी थ्रेड आहे! माझे नाव थ्रेड -3 आहे मी थ्रेड आहे! माझे नाव थ्रेड-1 मी धागा आहे! माझे नाव थ्रेड आहे -2 मी धागा आहे! माझे नाव थ्रेड -6 आहे मी थ्रेड आहे! माझे नाव थ्रेड आहे -4 मी थ्रेड आहे! माझे नाव थ्रेड-9 आहे मी थ्रेड आहे! माझे नाव थ्रेड-5 आहे मी थ्रेड आहे! माझे नाव थ्रेड-7 आहे मी थ्रेड आहे! माझे नाव थ्रेड-8 आहे
मल्टीथ्रेडिंगद्वारे निर्माण झालेल्या समस्या
आमच्या पुस्तकांच्या उदाहरणामध्ये, तुम्ही पाहिले आहे की मल्टीथ्रेडिंग अतिशय महत्त्वाची कामे सोडवते आणि आमचे प्रोग्राम जलद बनवू शकते. अनेकदा अनेक वेळा वेगवान. पण मल्टीथ्रेडिंग हा अवघड विषय मानला जातो. खरंच, अयोग्यरित्या वापरल्यास, ते सोडवण्याऐवजी समस्या निर्माण करतात. जेव्हा मी 'समस्या निर्माण करतो' म्हणतो, तेव्हा माझा अर्थ काही अमूर्त अर्थाने होत नाही. मल्टीथ्रेडिंगमुळे दोन विशिष्ट समस्या निर्माण होऊ शकतात: डेडलॉक आणि रेस कंडिशन. डेडलॉक ही अशी परिस्थिती आहे जिथे एकापेक्षा जास्त थ्रेड एकमेकांकडे असलेल्या संसाधनांची वाट पाहत आहेत आणि त्यापैकी कोणीही चालू ठेवू शकत नाही. आम्ही पुढील धड्यांमध्ये याबद्दल अधिक बोलू. आतासाठी खालील उदाहरण पुरेसे आहे: कल्पना करा की थ्रेड-1 काही ऑब्जेक्ट-1 शी संवाद साधतो आणि थ्रेड-2 ऑब्जेक्ट-2 शी संवाद साधतो. शिवाय, प्रोग्राम असे लिहिले आहे की:- थ्रेड-1 ऑब्जेक्ट-1 शी संवाद साधणे थांबवतो आणि थ्रेड-2 ऑब्जेक्ट-2 शी संवाद साधणे थांबवताच ऑब्जेक्ट-2 वर स्विच करतो आणि ऑब्जेक्ट-1 वर स्विच करतो.
- थ्रेड-2 ऑब्जेक्ट-2 शी संवाद साधणे थांबवतो आणि थ्रेड-1 ऑब्जेक्ट-1 शी संवाद थांबवताच ऑब्जेक्ट-1 वर स्विच करतो आणि ऑब्जेक्ट-2 वर स्विच करतो.
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 हा विनोदी दिनक्रम आहे का? :) आणि सर्व कारण आमच्या प्रोग्रामचे कार्य थ्रेड्सच्या अंमलबजावणीच्या क्रमावर अवलंबून आहे. आवश्यक अनुक्रमाचे थोडेसे उल्लंघन केल्याने, आमचे स्वयंपाकघर नरकात बदलते आणि एक वेडा रोबोट त्याच्या सभोवतालच्या सर्व गोष्टींचा नाश करतो. मल्टीथ्रेड प्रोग्रामिंगमध्ये ही देखील एक सामान्य समस्या आहे. तुम्ही त्याबद्दल एकापेक्षा जास्त वेळा ऐकाल. या धड्याचा समारोप करताना, मला मल्टीथ्रेडिंगबद्दल पुस्तकाची शिफारस करायची आहे. 'जावा कॉन्करन्सी इन प्रॅक्टिस' 2006 मध्ये लिहिले गेले होते, परंतु त्याची प्रासंगिकता गमावली नाही. हे मल्टीथ्रेडेड Java प्रोग्रामिंगसाठी समर्पित आहे — मूलभूत गोष्टींपासून ते सर्वात सामान्य चुका आणि अँटीपॅटर्नपर्यंत. जर तुम्ही एखाद्या दिवशी मल्टीथ्रेडिंग गुरू बनण्याचे ठरवले तर हे पुस्तक आवर्जून वाचावे लागेल. पुढील धड्यांमध्ये भेटू! :)
GO TO FULL VERSION