धाराओं। थ्रेड क्लास और रननेबल इंटरफ़ेस। थ्रेड क्लास ए सुवे धागा
- थ्रेड प्राथमिकताएँ क्या हैं?
इस सवाल का जवाब कोडग्म व्याख्यान में है।
थ्रेड्स के समानांतर संचालन का अनुकूलन करने के लिए, जावा में थ्रेड प्राथमिकताएं सेट करने की क्षमता है। उच्च प्राथमिकता वाले थ्रेड्स को कम प्राथमिकता वाले थ्रेड्स पर CPU समय प्राप्त करने का लाभ है।
थ्रेड क्लास के निम्नलिखित तरीकों द्वारा प्राथमिकता हैंडलिंग प्रदान की जाती है:
सार्वजनिक अंतिम शून्य सेटपैरिटी (इंट न्यूपायरिटी)
धागे की प्राथमिकता निर्धारित करता है।
सार्वजनिक अंतिम इंट गेटपैरिटी ()
आपको थ्रेड की प्राथमिकता पता है।
सेटपैरिटी पद्धति में पैरामीटर मान मनमाना नहीं हो सकता है। इसमें MIN_PRIORITY से लेकर MAX_PRIORITY तक होनी चाहिए। इसे बनाते समय थ्रेड में NORM_PRIORITY प्राथमिकता है।
MIN_PRIORITY \u003d 1।
NORM_PRIORITY \u003d 5।
MAX_PRIORITY \u003d 10। - बहुत सारे धागे बनाएँ, और संसाधन व्यर्थ हैं और समय भी किसी भी अप्रयुक्त धागे का निर्माण करते हैं
- कई थ्रेड्स को नष्ट करें और अधिक समय बाद में उन्हें फिर से बनाने में खर्च किया जाएगा
- थ्रेड बनाना बहुत धीरे-धीरे ग्राहक के खराब प्रदर्शन (लंबे समय तक प्रतीक्षा समय) के कारण हो सकता है
क्या मैं अपनी प्राथमिकता 0 पर कम करके एक धागा रोक सकता हूं?
लेख में उत्तर: “शीर्ष 50 साक्षात्कार प्रश्न। विषय: बहुआयामी "
मंच पर मिला।
इस लेख का एक अंग्रेजी संस्करण है: शीर्ष 50 जावा थ्रेड साक्षात्कार प्रश्न फ्रेशर्स, अनुभवी प्रोग्रामर के लिए उत्तर
जावा सब कुछ के लिए समृद्ध एपीआई प्रदान करता है, लेकिन, विडंबना यह है कि एक धागा को रोकने के लिए सुविधाजनक तरीके प्रदान नहीं करता है। JDK 1.0 में, स्टॉप (), सस्पेंड (), और फिर से शुरू () के रूप में कई नियंत्रण विधियां थीं जिन्हें चिह्नित किया गया है पदावनत संभावित गतिरोध के खतरों के कारण भविष्य के रिलीज में, जावा एपीआई डेवलपर्स ने तब से कोई प्रयास नहीं किया है, ताकि थ्रेड्स को रोकने के लिए एक टिकाऊ, थ्रेड-सुरक्षित और सुरुचिपूर्ण तरीका प्रदान किया जा सके। प्रोग्रामर ज्यादातर इस बात पर भरोसा करते हैं कि जैसे ही वह रन () या कॉल () के तरीकों को अंजाम देता है, धागा खुद को रोक लेता है। मैनुअल रोक के लिए, प्रोग्रामर एक अस्थिर बूलियन चर का लाभ उठाते हैं और प्रत्येक पुनरावृत्ति में इसके मूल्य की जांच करते हैं यदि रन () विधि में लूप होते हैं, या अचानक (रद्द) विधि के साथ थ्रेड्स जॉब्स को रद्द कर देते हैं।
विशेष रूप से इस सवाल पर: मैंने कभी किसी को 0 पर प्राथमिकता तय करते नहीं देखा।
अगर किसी को इस बारे में कुछ भी पता है, तो टिप्पणियों में लिखें।
थ्रेडग्रुप की आवश्यकता क्यों है?
थ्रेडग्रुप धागे का एक संग्रह है जिसमें अन्य थ्रेड समूह भी हो सकते हैं। धागे का एक समूह एक पेड़ बनाता है जिसमें धागे के हर दूसरे समूह में एक माता-पिता होते हैं (मूल एक को छोड़कर)। एक थ्रेड में अपने स्वयं के थ्रेडग्रुप से डेटा तक पहुंच होती है, लेकिन अन्य समूहों या पैरेंट थ्रेडग्रुप तक ऐसी पहुंच नहीं होती है।
धागों का समूह मुख्य-सूत्र किसमें है?
मुझे यह कहीं भी नहीं मिला)) मुझे बताओ कि यह कहां है))
थ्रेडपूल पैटर्न क्या है?
इस पर विकिपीडिया लेख का एक अंश है:
कंप्यूटर प्रोग्रामिंग में, थ्रेड पूल पैटर्न (भी दोहराया श्रमिकों या कार्यकर्ता-चालक मॉडल) वह जगह है जहां कई कार्य करने के लिए कई थ्रेड बनाए जाते हैं, जो आमतौर पर एक कतार में आयोजित किए जाते हैं। निष्पादित किए जा रहे कार्यों के परिणामों को भी एक कतार में रखा जा सकता है, या कार्य कोई परिणाम नहीं दे सकते हैं (उदाहरण के लिए, यदि कार्य एनीमेशन के लिए है)। आमतौर पर, थ्रेड्स की तुलना में कई अधिक कार्य होते हैं। जैसे ही एक धागा अपना कार्य पूरा करता है, यह कतार से अगले कार्य का अनुरोध करेगा जब तक कि सभी कार्य पूर्ण नहीं हो जाते। धागा तब तक समाप्त हो सकता है, या तब तक सो सकता है जब तक कि नए कार्य उपलब्ध न हों।
उपयोग किए जाने वाले थ्रेड्स की संख्या एक पैरामीटर है जिसे सर्वश्रेष्ठ प्रदर्शन प्रदान करने के लिए ट्यून किया जा सकता है। इसके अतिरिक्त, थ्रेड्स की संख्या प्रतीक्षा कार्यों की संख्या के आधार पर गतिशील हो सकती है। उदाहरण के लिए, एक वेब सर्वर थ्रेड्स जोड़ सकता है यदि कई वेब पेज अनुरोध आते हैं और उन अनुरोधों को समाप्त करने पर थ्रेड्स निकाल सकते हैं। एक बड़ा थ्रेड पूल होने की लागत संसाधन उपयोग में वृद्धि है। थ्रेड बनाने या नष्ट करने के लिए निर्धारित करने के लिए उपयोग किए जाने वाले एल्गोरिदम का समग्र प्रदर्शन पर प्रभाव पड़ेगा:
कंप्यूटर प्रोग्रामिंग में एक थ्रेड पूल मॉडल है जहां विभिन्न प्रकार के कार्यों को करने के लिए विशिष्ट संख्या में थ्रेड बनाए जाते हैं, जो आमतौर पर कतारबद्ध होते हैं। पूर्ण किए गए कार्यों के परिणाम भी पंक्तिबद्ध किए जा सकते हैं, या कार्य किसी भी परिणाम को नहीं लौटा सकते हैं (उदाहरण के लिए, यदि कार्य एनीमेशन के लिए है)।
आमतौर पर, थ्रेड्स की तुलना में कई अधिक कार्य होते हैं। एक बार जब धागा अपना कार्य पूरा कर लेता है, तो यह कतार से अगले कार्य का अनुरोध करेगा जब तक कि सभी कार्य पूर्ण नहीं हो जाते। प्रवाह तब बाधित या सो सकता है। उपयोग किए जाने वाले थ्रेड्स की संख्या एक पैरामीटर है जिसे सर्वश्रेष्ठ प्रदर्शन प्रदान करने के लिए ट्यून किया जा सकता है। इसके अलावा, थ्रेड की संख्या उत्पन्न होने वाले कार्यों की संख्या के आधार पर गतिशील हो सकती है। उदाहरण के लिए, यदि कई वेब पेज से अनुरोध आते हैं, और कम अनुरोध होने पर धाराएं हटा सकते हैं, एक वेब सर्वर स्ट्रीम जोड़ सकता है। जैसे-जैसे थ्रेड पूल का आकार बढ़ता जाता है, कंप्यूटर संसाधनों का उपयोग बढ़ता जाता है। थ्रेड बनाने या नष्ट करने के लिए निर्धारित करने के लिए उपयोग किए जाने वाले एल्गोरिदम का समग्र प्रदर्शन पर प्रभाव पड़ेगा: - बहुत अधिक थ्रेड बनाना संसाधनों और समय को बर्बाद कर रहा है।
कई थ्रेड्स को नष्ट करें और उन्हें बनाने के लिए अधिक समय बाद में फिर से खर्च किया जाएगा - थ्रेड बनाना बहुत धीरे-धीरे ग्राहक प्रदर्शन को कम कर सकता है।
ThreadPoolExecutor की आवश्यकता क्यों है?
सार्वजनिक वर्ग ThreadPoolExecutor AbstractExecutorService का विस्तार करता है
एक ExecutorService यह संभवतः प्रत्येक जमा किए गए थ्रेड्स में से एक का उपयोग करके प्रत्येक सबमिट किए गए कार्य को निष्पादित करता है, आमतौर पर एक्ज़ीक्यूटर्स फ़ैक्टरी विधियों का उपयोग करके कॉन्फ़िगर किया जाता है।
थ्रेड पूल दो अलग-अलग मुद्दों को संबोधित करते हैं: वे आम तौर पर प्रति कार्य कॉल ओवरहेड कम होने के कारण बड़ी संख्या में अतुल्यकालिक कार्यों का प्रदर्शन करके बेहतर प्रदर्शन प्रदान करते हैं, और वे कार्यों के एक सेट को निष्पादित करते समय उपयोग किए जाने वाले थ्रेड सहित संसाधनों को सीमित करने और नियंत्रित करने का साधन प्रदान करते हैं। प्रत्येक ThreadPoolExecutor कुछ बुनियादी आँकड़ों को भी बनाए रखता है जैसे कि पूर्ण किए गए कार्यों की संख्या।
संदर्भों की एक विस्तृत श्रृंखला में उपयोगी होने के लिए, यह वर्ग कई समायोज्य पैरामीटर और एक्स्टेंसिबिलिटी लीवर प्रदान करता है। हालाँकि, प्रोग्रामर को अधिक सुविधाजनक एक्ज़ीक्यूटर्स फ़ैक्टरी विधियों Executors.newCachedThreadPool () (अनलिमिटेड थ्रेड पूल, स्वचालित थ्रेड रिकवरी के साथ), Executors.newFixedThreadPool (int) (निश्चित आकार थ्रेड पूल) और Executors.newSingleThreadExecutor () (श्रेष्ठ थ्रेड) का उपयोग करने के लिए प्रोत्साहित किया जाता है। जो सबसे आम उपयोग के मामलों के लिए सेटिंग्स को पूर्व-कॉन्फ़िगर करते हैं।
एक धागा बनाने के लिए आप कितने तरीके जानते हैं?
भाषा के स्तर पर, एक धागा बनाने के दो तरीके हैं। Java.lang.Thread क्लास ऑब्जेक्ट एक थ्रेड है, लेकिन इसे चलाने के लिए एक कार्य की आवश्यकता होती है, जो कि java.lang.Runnable इंटरफ़ेस को लागू करने वाली ऑब्जेक्ट है। चूंकि थ्रेड क्लास रननेबल इंटरफ़ेस को लागू करता है, आप थ्रेड से अपनी क्लास को इनहेरिट करके या इसमें रननेबल इंटरफ़ेस को लागू करके रन () विधि को ओवरराइड कर सकते हैं।
भविष्य वर्ग किसके लिए प्रयोग किया जाता है?
भविष्य एक अतुल्यकालिक गणना के परिणाम को संग्रहीत करता है। आप किसी को फ्यूचर ऑब्जेक्ट देकर कंपटीशन शुरू कर सकते हैं और इसके बारे में भूल सकते हैं। भविष्य की वस्तु का स्वामी परिणाम तैयार होने पर प्राप्त कर सकता है।
Runnable पर Callable के क्या फायदे हैं?
कॉल करने योग्य इंटरफ़ेस रनने योग्य इंटरफ़ेस या थ्रेड वर्ग की तुलना में समानांतर निष्पादन के लिए डिज़ाइन किए गए कार्यों को बनाने के लिए अधिक उपयुक्त है। यह ध्यान दिया जाना चाहिए कि इस तरह के एक इंटरफ़ेस को जोड़ने की क्षमता केवल जावा 5 संस्करण के साथ शुरू हुई, क्योंकि कॉल करने योग्य इंटरफ़ेस की प्रमुख विशेषता पैरामीटराइज्ड प्रकार (जेनरिक) का उपयोग है, जैसा कि लिस्टिंग में दिखाया गया है।
कॉल करने योग्य इंटरफ़ेस 10 1 आयात जावा का उपयोग करके कार्य बनाना। util। समवर्ती। प्रतिदेय; 11 2 सार्वजनिक वर्ग CallableSample इम्प्लीमेंट्स Callable (12 3 public String call () थ्रेड अपवाद (13 4 if (कुछ कंडीशन)) (14 5 new IOException (फेंकें) "कार्य प्रसंस्करण के दौरान त्रुटि"); १५ ६) १६ System प्रणाली। बाहर। Println ("कार्य प्रसंस्करण है"); 17 8 वापसी "परिणाम"; १ ९) १ ९ १०)
आपको तुरंत लाइन 2 पर ध्यान देना चाहिए, जहां यह इंगित किया गया है कि कॉल करने योग्य इंटरफ़ेस को मानकीकृत किया गया है, और इसका ठोस कार्यान्वयन, कॉल करने योग्य नमूना वर्ग, स्ट्रिंग प्रकार पर निर्भर करता है। लाइन 3 पहले से ही मानकीकृत संस्करण में मुख्य कॉल विधि के हस्ताक्षर को दर्शाता है, क्योंकि रिटर्न वैल्यू का प्रकार भी स्ट्रिंग पर सेट है। वास्तव में, इसका मतलब है कि एक कार्य बनाया गया था, जिसके परिणामस्वरूप स्ट्रिंग का प्रकार होगा (पंक्ति 8 देखें)। इसी तरह, आप एक ऐसा कार्य बना सकते हैं जो कॉल विधि में किसी भी आवश्यक प्रकार का ऑब्जेक्ट बना और वापस कर देगा। रननेबल इंटरफ़ेस में रन विधि की तुलना में यह समाधान बहुत अधिक सुविधाजनक है, जो कुछ भी नहीं लौटाता है (इसकी वापसी का प्रकार शून्य है) और इसलिए आपको कार्य का आउटपुट प्राप्त करने के लिए वर्कआर्स का आविष्कार करना होगा।
कॉल करने योग्य इंटरफ़ेस का एक अन्य लाभ अन्य चल रहे कार्यों को प्रभावित किए बिना अपवादों को "फेंक" करने की क्षमता है। लाइन 3 इंगित करता है कि एक अपवाद एक विधि से "फेंका" जा सकता है, जो प्रभावी रूप से किसी भी प्रकार के अपवाद का मतलब है, क्योंकि सभी अपवाद java.lang.Exception के वंशज हैं। पंक्ति 5 एक चेक IOException को फेंकने के लिए इस सुविधा का उपयोग करता है। रननेबल इंटरफ़ेस की रन विधि ने नियंत्रित अपवादों को बिल्कुल भी फेंकने की अनुमति नहीं दी, और एक अनियंत्रित (रनटाइम) अपवाद को फेंकने से थ्रेड और पूरे एप्लिकेशन को रोक दिया गया।
क्या फ्यूचर क्लास का उपयोग करके कोई कार्य रद्द किया जा सकता है?
इस चर्चा के आधार पर, हैबे पर उठाया गया, यह पता चला है कि यह असंभव है।
भविष्य में Future.cancel (बूलियन) विधि है जो कार्य के निष्पादन को रद्द कर देना चाहिए। लेकिन अगर कार्य पहले ही निष्पादित करना शुरू कर दिया है, तो Future.cancel (सच) को कॉल करना वास्तव में इसे बंद नहीं करेगा। FutureTask कार्यान्वयन की गहराई में, निम्नलिखित कोड निष्पादित किया गया है:
if (mayInterruptIfRunning) (थ्रेड आर \u003d रनर; अगर (आर! \u003d नल)। रुकावट (;);)उन। फिर, कार्य को चलाने वाले थ्रेड को केवल निष्पादित करने से रोकने की सलाह दी जाती है। इसके अतिरिक्त, हमारे पास यह जानने की क्षमता भी नहीं है कि वर्तमान में कार्य निष्पादित किया जा रहा है या नहीं। Future.isDone () पद्धति है, लेकिन फिर से, यह वापस आ जाती है सच न केवल जब कार्य ने निष्पादन पूरा कर लिया है, लेकिन Future.cancel () को कॉल करने के तुरंत बाद, भले ही कार्य अभी भी निष्पादित हो रहा है (आखिरकार, Future.cancel (सत्य) उस कार्य को रोक नहीं सकता है जो पहले से ही निष्पादित करना शुरू कर चुका है)।
ठीक है, अगर हम सभी कोड स्वयं लिखते हैं, तो हम सही स्थानों पर थ्रेड.इज़इंटरप्टेड () को सावधानीपूर्वक संभाल सकते हैं और सब कुछ ठीक होगा। लेकिन अगर हम थर्ड पार्टी कोड चलाते हैं? क्या हमें प्लगइन्स के साथ एक्स्टेंसिबल होना चाहिए? कोई भी टेढ़ा लिखा प्लगइन आसानी से पूरे सर्वर के निष्क्रिय अवस्था में ले जा सकता है, क्योंकि हम त्रिशंकु प्लगइन के निष्पादन को सही ढंग से बाधित नहीं कर सकते हैं।
रूसी शब्दावली में, शब्द धागा "स्ट्रीम" का अनुवाद मजबूत हो गया है। यद्यपि इस शब्द का अनुवाद "थ्रेड" के रूप में भी किया जा सकता है। कभी-कभी विदेशी शैक्षिक सामग्रियों में प्रवाह की अवधारणा को थ्रेड्स पर सटीक रूप से समझाया गया है। आइए तार्किक श्रृंखला जारी रखें - जहां धागे हैं, एक उलझन है। और जहां एक उलझन है, वहां एक बिल्ली है। यह तुरंत स्पष्ट है कि अनुवादकों के पास बिल्लियाँ नहीं थीं। और इसलिए भ्रम पैदा हो गया। इसके अलावा, शब्द के तहत अन्य धाराएँ हैं धारा... अनुवादक आमतौर पर अजीब लोग हैं।
जब कोई अनुप्रयोग शुरू होता है, तो एक थ्रेड कहा जाता है मुख्य धारा (मुख्य)। इससे बच्चे के धागे पैदा होते हैं। मुख्य धागा आमतौर पर कार्यक्रम निष्पादन को समाप्त करने वाला अंतिम धागा है।
इस तथ्य के बावजूद कि मुख्य धागा स्वचालित रूप से बनाया गया है, इसे कक्षा की एक वस्तु के माध्यम से नियंत्रित किया जा सकता है धागा... ऐसा करने के लिए, आपको विधि को कॉल करने की आवश्यकता है वर्तमान ()जिसके बाद आप प्रवाह को नियंत्रित कर सकते हैं।
कक्षा धागा धागे के प्रबंधन के लिए कई तरीके हैं।
- getName () - स्ट्रीम का नाम लें
- गेटपैरिटी () - थ्रेड को प्राथमिकता दें
- जीवित है () - निर्धारित करें कि क्या एक धागा चल रहा है
- शामिल हों () - धारा के अंत की प्रतीक्षा करें
- daud () - धारा की शुरुआत। इसमें अपना कोड लिखें
- नींद () - एक निर्दिष्ट समय के लिए स्ट्रीम को रोकें
- शुरू () - स्ट्रीम शुरू करें
आइए मुख्य धागे के बारे में जानकारी प्राप्त करें और इसका नाम बदलें।
थ्रेड mainThread \u003d Thread.currentThread (); mInfoTextView.setText ("वर्तमान थ्रेड:" + mainThread.getName ()); // नाम बदलें और इसे टेक्स्ट फ़ील्ड mainThread.setName ("कैटट्रेड") में प्रदर्शित करें; mInfoTextView.append ("\\ n नया धागा नाम:" + mainThread.getName ());
डिफ़ॉल्ट मुख्य थ्रेड नाम मुख्यजिसे हमने बदल दिया CatThread.
चलो विधि निर्दिष्ट किए बिना धारा के नाम के बारे में जानकारी कहते हैं।
थ्रेड mainThread \u003d Thread.currentThread (); mInfoTextView.setText ("वर्तमान थ्रेड:" + mainThread);
इस मामले में, आप लाइन देख सकते हैं धागा - धारा का नाम, उसकी प्राथमिकता और उसके समूह का नाम।
अपनी खुद की स्ट्रीम बनाएं
अपनी खुद की स्ट्रीम बनाना कठिन नहीं है। यह वर्ग से विरासत में पर्याप्त है धागा.
आइए हमारी कक्षा के अंदर एक आंतरिक वर्ग की घोषणा करें और इसे क्लिक करके विधि को कॉल करें शुरू ().
सार्वजनिक वर्ग MyThread थ्रेड (सार्वजनिक शून्य रन) () (Log.d (TAG, "मेरा धागा है ...");)) सार्वजनिक शून्य onClick (दृश्य देखें) (MyThread myThread \u003d new Myhhread) (); MyThread.start ( );)
वैकल्पिक रूप से, विधि कॉल स्थगित करें शुरू () कंस्ट्रक्टर में।
सार्वजनिक शून्य onClick (दृश्य देखें) (MyThread myThread \u003d new MyThread ();) सार्वजनिक वर्ग MyThread थ्रेड फैली हुई है (// कन्स्ट्रक्टर MyThread) () (// एक नया थ्रेड सुपर ("दूसरा धागा") बनाएँ; Log.i (TAG, ") दूसरा धागा "+ यह) बनाया; प्रारंभ (); // धागा प्रारंभ करें) सार्वजनिक शून्य रन () (Log.d (TAG," मेरा धागा शुरू हो गया है ... "); कोशिश करें (के लिए (int i \u003d 5; i\u003e) 0; i--) (लॉग.आई (टीएजी, "दूसरा धागा:" + i); थ्रेड.स्लीप (500);)) कैच (इंटरप्टेड एक्सेप्शन ई) (लॉग.आई (टीएजी, "दूसरा थ्रेड बाधित"); )))
एक रनवेबल थ्रेड बनाना
स्ट्रीम बनाने के लिए अधिक जटिल विकल्प है। एक नया धागा बनाने के लिए, आपको इंटरफ़ेस को लागू करने की आवश्यकता है runnable... आप इंटरफ़ेस को लागू करने वाले किसी भी ऑब्जेक्ट से एक स्ट्रीम बना सकते हैं runnable और विधि घोषित करें daud ().
अंदर की विधि daud () आप नए थ्रेड के लिए कोड पोस्ट करते हैं। विधि वापस आने पर यह धागा समाप्त हो जाएगा।
जब आप एक इंटरफ़ेस के साथ एक नया वर्ग घोषित करते हैं runnable, आपको कंस्ट्रक्टर का उपयोग करने की आवश्यकता है:
थ्रेड (रन करने योग्य थ्रेड_बॉजेक्ट, स्ट्रिंग थ्रेड_name)
पहला पैरामीटर इंटरफ़ेस को लागू करने वाले वर्ग का एक उदाहरण निर्दिष्ट करता है। यह परिभाषित करता है कि जहां धागा निष्पादित करना शुरू कर देगा। दूसरा पैरामीटर स्ट्रीम का नाम है।
एक नया धागा बनाने के बाद, आपको विधि का उपयोग करके इसे शुरू करने की आवश्यकता है शुरू ()जो अनिवार्य रूप से एक विधि कॉल करता है daud ().
आइए एक नेस्टेड क्लास के रूप में ट्यूटोरियल प्रोजेक्ट के अंदर एक नया धागा बनाएं और इसे चलाएं।
पैकेज ru.alexanderklimov.expresscourse; आयात android.os.Bundle; import android.support.v7.app.AppCompatActivity; आयात android.util.Log; आयात android.view.View; आयात android.widget.Button; आयात android.widget.EditText; आयात android.widget.TextView; आयात स्थैतिक ru.alexanderklimov.expresscourse.R.id.textViewInfo; सार्वजनिक वर्ग MainActivity का विस्तार AppCompatActivity (अंतिम स्ट्रिंग TAG \u003d "ExpressCourse"; प्राइवेट बटन mButton; निजी EditText mResultEditText; निजी पाठ दृश्य mInfoTextView; @Override संरक्षित शून्य onCreate (बंडल सेवइन्स्टटस्टैट) (save.Create) (save.Create) से किया गया है। ); mButton \u003d (बटन) findViewById (R.id.buttonGetResult); mResultEditText \u003d (EditText) findViewById (R.id.edititext); mInfoTextView \u003d (TextView) findViewById (textViewInfo) (देखें)। MyRunnable (); // एक नया थ्रेड ट्राई करें (for (int i \u003d 5; i\u003e 0; i--) (Log.i (TAG, "Main thread:" + i); थ्रेड.स्लीप (1000);) ) पकड़ (InterruptedException e) (Log.i (TAG, "मुख्य धागा बाधित");)) वर्ग MyRunnable लागू करना Runnable (थ्रेड थ्रेड; // कंस्ट्रक्टर MyRunnable) () (// एक नया दूसरा थ्रेड थ्रेड बनाएँ \u003d नया थ्रेड \u003d नया थ्रेड; "नमूना धागा"); Log.i (TAG, "दूसरा धागा बनाया" + धागा); थ्रेड.स्टार्ट (); // n ओटोक) // रननेबल इंटरफ़ेस पब्लिक शून्य रन के लिए आवश्यक विधि () (प्रयास (के लिए (i i \u003d 5); i\u003e 0; i--) (Log.i (TAG, "दूसरा धागा:" + i); थ्रेड.स्लीप (500);)) पकड़ (InterruptedException e) (Log.i (TAG, "दूसरा थ्रेड बाधित");); ))
कंस्ट्रक्टर के अंदर MyRunnable () हम एक नई कक्षा वस्तु बनाते हैं धागा
थ्रेड \u003d नया थ्रेड (यह, "उदाहरण थ्रेड");
पहले पैरामीटर ने ऑब्जेक्ट का उपयोग किया यहजिसका मतलब है कि विधि को कॉल करना चाहते हैं daud () यह वस्तु। फिर विधि कहा जाता है शुरू (), जिसके परिणामस्वरूप थ्रेड का निष्पादन विधि के साथ शुरू होता है daud ()... बदले में, विधि हमारे धागे के लिए एक लूप शुरू करती है। कॉल करने के बाद विधि शुरू (), निर्माता MyRunnable () एप्लिकेशन पर नियंत्रण लौटाता है। जब मुख्य धागा अपना काम जारी रखता है, तो यह अपने पाश में प्रवेश करता है। दोनों धागे फिर समानांतर में चलते हैं।
आप पहले के अलावा केवल एक दूसरा धागा ही नहीं, बल्कि कई सूत्र चला सकते हैं। इससे समस्याएं हो सकती हैं जब दो धागे एक ही समय में एक ही चर के साथ काम करने की कोशिश करते हैं।
सिंक्रोनाइज़्ड कीवर्ड - सिंक्रोनाइज़्ड मेथड्स
सिंक्रनाइज़ेशन का उपयोग थ्रेड्स के साथ समस्या को हल करने के लिए किया जाता है जो भ्रम पैदा कर सकता है।
विधि में एक संशोधक हो सकता है सिंक्रनाइज़... जब एक थ्रेड एक सिंक्रनाइज़ विधि के अंदर होता है, तो अन्य सभी थ्रेड्स जो इसे उसी उदाहरण पर कॉल करने का प्रयास करते हैं, को प्रतीक्षा करनी चाहिए। जब कई सूत्र एक विधि को कॉल करने का प्रयास करते हैं तो यह भ्रम से बचा जाता है।
सिंक्रोनाइज़्ड शून्य म्याऊ (स्ट्रिंग संदेश);
इसके अलावा, कीवर्ड सिंक्रनाइज़ एक ऑपरेटर के रूप में इस्तेमाल किया जा सकता है। आप ब्लॉक कर सकते हैं सिंक्रनाइज़ कुछ वर्ग के तरीकों के लिए कॉल:
सिंक्रोनाइज्ड (ऑब्जेक्ट) (// सिंक्रनाइज़ेशन की आवश्यकता वाले बयान)
Looper
धारा में संस्थाएँ हैं Looper, हैंडलर, MessageQueue.
प्रत्येक धारा में एक अद्वितीय है Looper और कई हो सकते हैं हैंडलर.
गिनती Looper एक सहायक थ्रेड ऑब्जेक्ट जो इसे प्रबंधित करता है। यह आने वाले संदेशों को संसाधित करता है, और थ्रेड को सही समय पर बाहर निकलने का निर्देश भी देता है।
धारा अपनी हो जाती है Looper तथा MessageQueue विधि के माध्यम से Looper.prepare () लॉन्च के बाद। Looper.prepare () कॉलिंग थ्रेड की पहचान करता है, बनाता है Looper तथा MessageQueue और दुकान में उनके लिए धारा बांधता है ThreadLocal... तरीका लूपर। लूप () चलाने के लिए बुलाया जाना चाहिए Looper... आप इसका काम विधि के माध्यम से पूरा कर सकते हैं looper.quit ().
Class LooperThread थ्रेड (सार्वजनिक हैंडलर mHandler; सार्वजनिक शून्य रन) (Looper.pare (); mHandler \u003d नया हैंडलर () (सार्वजनिक शून्य हैंडलमैसेज (संदेश संदेश)) // // यहाँ आने वाले संदेशों को फैलाता है) (Looper.loop (); ;))
एक स्थिर विधि का उपयोग करें getMainLooper () उपयोग करने के लिए Looper मुख्य धागा:
लूपर मेनलॉपर \u003d लोपर.गेटमैनऑपर ();
दो धाराएँ बनाते हैं। हम एक को मुख्य धागे में और दूसरे को मुख्य धागे से अलग से लॉन्च करेंगे। दो बटन और एक लेबल हमारे लिए पर्याप्त होगा।
ध्यान दें कि धागे कैसे शुरू किए जाते हैं। पहला धागा विधि का उपयोग करके शुरू किया गया है शुरू (), और दूसरा - daud ()... फिर हम जांचते हैं कि हम किस धागे में हैं।
पैकेज ru.alexanderklimov.as23; आयात android.os.Bundle; आयात android.os.Looper; import android.support.v7.app.AppCompatActivity; आयात android.view.View; आयात android.widget.Button; आयात android.widget.TextView; सार्वजनिक वर्ग MainActivity का विस्तार AppCompatActivity (TextView mInfoTextView; @Override संरक्षित शून्य onCreate (बंडल saveInstanceState) (super.onCreate (saveInstanceState)); setContentView (R.layout.activity_main); बटन startButton \u003d बटन बटन से किया गया है। बटन runButton \u003d (बटन) findViewById (R.id.button_run); mInfoTextView \u003d (TextView) findViewById (R.id.textview_info); startButton.setOnClickListener (नया दृश्य .nClickListener) (@Override- public_ride) थ्रेड थ्रेड \u003d नया थ्रेड (नया MyRunnable ()); थ्रेड.स्टार्ट (; // एक बैकग्राउंड पर)))); रनबटन.सेटऑनऑलक्लिक लिसनर (नया View.OnClickListener) () (@Override public void onClick (View view) (थ्रेड थ्रेड) \u003d नया थ्रेड (नया MyRunnable ()); थ्रेड .run (; // वर्तमान थ्रेड में)));) प्राइवेट क्लास MyRunnable इम्प्लांट रननीय (@Override public void run) (// चेक करें कि हम कौन से थ्रेड में हैं; Looper.getMainLooper ()। GetThread () \u003d\u003d Thread.currentThread ()) (mInfoText) View.setText ("मुख्य धागे पर"); ) और (runOnUiThread (नया Runnable) () (@Override public void run () (mInfoTextView.setText ("बैकग्राउंड थ्रेड" पर;)));))));
यह विषय काफी जटिल है और बहुमत के लिए यह रुचि और अध्ययन की आवश्यकता नहीं है।
एंड्रॉइड में, शुद्ध धाराओं का कम और कम उपयोग किया जाता है, सिस्टम के अपने तरीके हैं।
एक सिंक्रनाइज़ ब्लॉक में प्रवेश करते समय एक धागा क्या राज्यों में प्रवेश कर सकता है?
- runnable
- अवरोधित
RUNNABLE में, यदि कोड के ब्लॉक को सिंक्रनाइज़ किया गया है, तो किसी अन्य थ्रेड द्वारा कब्जा नहीं किया गया है। अन्यथा, हमारा धागा ब्लॉक किए गए राज्य को प्राप्त करेगा और म्यूटेक्स ऑब्जेक्ट के रिलीज़ होने की प्रतीक्षा करेगा।
इस विधि को कॉल करने से थ्रेडिंग स्थिति में होती है।
प्रतीक्षा () विधि को केवल एक म्यूटेक्स ऑब्जेक्ट के सिंक्रनाइज़ ब्लॉक के अंदर बुलाया जा सकता है जिसे वर्तमान थ्रेड द्वारा लॉक (लॉक) किया गया है, अन्यथा विधि अपवाद को फेंक देगी IllegalMonitorStateException.
ऑब्जेक्ट मॉनिटर \u003d getMonitor (); सिंक्रनाइज़ (मॉनिटर) (… मॉनिटर। प्रतीक्षा ();…)
जब प्रतीक्षा () विधि कहा जाता है, तो वर्तमान थ्रेड मॉनिटर ऑब्जेक्ट को अनलॉक करता है और WAITING स्थिति में प्रवेश करता है, मॉनीटर को नोट करने के लिए एक और थ्रेड की प्रतीक्षा कर रहा है। नोट () या मॉनिटर.नोटिफाइऑल () विधि। जैसे ही ऐसा होता है, धागा जाग जाएगा और अगर मॉनिटर व्यस्त नहीं था, तो यह इसे पकड़ लेगा और काम करना जारी रखेगा।
प्रतीक्षा (500) विधि कहा जाता है जब धागा किस राज्य में जाएगा?
इस विधि को कॉल करने से TIMED_WAITING स्थिति में थ्रेड होता है।
प्रतीक्षा () विधि के साथ सादृश्य द्वारा, प्रतीक्षा (टाइमआउट) को केवल एक म्यूटेक्स ऑब्जेक्ट के सिंक्रनाइज़ ब्लॉक के अंदर बुलाया जा सकता है जिसे वर्तमान थ्रेड द्वारा लॉक (बंद) किया गया है। ऑब्जेक्ट मॉनिटर \u003d getMonitor (); सिंक्रनाइज़ (मॉनिटर) (… मॉनिटर। प्रतीक्षा (500);…)
जब प्रतीक्षा () विधि कहा जाता है, तो वर्तमान थ्रेड मॉनिटर ऑब्जेक्ट को अनलॉक करता है और 500 मिली सेकंड के लिए सो जाता है। मॉनिटर ऑब्जेक्ट को किसी अन्य थ्रेड द्वारा कैप्चर किया जा सकता है।
500 मिलीसेकंड के बाद, धागा जाग जाएगा और यदि मॉनिटर व्यस्त नहीं था, तो यह इसे पकड़ लेगा और काम करना जारी रखेगा।
यदि मॉनीटर को किसी अन्य थ्रेड द्वारा अधिग्रहित किया जाता है, तो वर्तमान थ्रेड BLOCKED स्थिति में प्रवेश करेगा।
अधिसूचित () विधि को कॉल करने पर धागा किस स्थिति में जाएगा?
ऑब्जेक्ट मॉनिटर \u003d getMonitor (); सिंक्रनाइज़ (मॉनिटर) (… मॉनिटर। प्रतीक्षा ();…)
मॉनिटर.वाइट () के बाद, थ्रेड WAITING स्थिति में प्रवेश करेगा। मॉनिटर ऑब्जेक्ट पर किसी अन्य थ्रेड द्वारा कॉल की जाने वाली सूचना () विधि थ्रेडिंग स्थिति से थ्रेड को हस्तांतरण योग्य स्थिति में स्थानांतरित कर देगा, यदि मॉनिटर ऑब्जेक्ट को किसी अन्य थ्रेड द्वारा कैप्चर नहीं किया गया है, अन्यथा, ब्लॉक की गई स्थिति में।
नोटिफिकेशन () विधि को कॉल करने पर धागा किस स्थिति में जाएगा?
NotifyAll () सभी थ्रेड को जगाएगा। सभी "स्लीपिंग" (WAITING) थ्रेड्स में से एक RUNNABLE स्थिति में प्रवेश करेगा, उपयोग में आने वाली वस्तु की निगरानी करेगा, और अपना काम जारी रखेगा। बाकी ब्लॉक स्थिति में होगा। जैसे ही पहला "जागृत" धागा मॉनीटर जारी करता है, जिसके लिए हर कोई इंतजार कर रहा है, उसके भाग्य को अगले थ्रेड द्वारा दोहराया जाएगा (ब्लॉक किए गए राज्य से एक मनमाना धागा रननेबल स्थिति में जाएगा)। यह तब तक जारी रहेगा जब तक सभी "जागृत" धागे ब्लॉक स्थिति को नहीं छोड़ देते।
सिंक्रनाइज़ ब्लॉक में तीन थ्रेड्स को म्यूटेक्स ऑब्जेक्ट पर प्रतीक्षा () कहा जाता है। अगर चौथा थ्रेड कॉन्टेक्टअल्स () को कॉल करेगा तो ये थ्रेड्स किस स्थिति में जाएंगे?
उनमें से दो ब्लॉक राज्य में जाएंगे, एक रननेबल राज्य में
(500) प्रतीक्षा (500) से कैसे अलग है?
हालाँकि दोनों जुड़ते हैं (५००) और प्रतीक्षा (५००) वर्तमान धागा TIMED_WAITING राज्य में डाल देंगे, दोनों के बीच महत्वपूर्ण अंतर हैं:
join (500) को थ्रेड पर बुलाया जाता है, वेट (500) को उस ऑब्जेक्ट पर सिंक्रोनाइज़्ड ब्लॉक के अंदर कहा जाता है, जिस पर यह ब्लॉक सिंक्रोनाइज़ होता है।
जब ज्वाइन (500) कहा जाता है, तो थ्रेड को पूरा करने के लिए वर्तमान थ्रेड 500 मिली सेकेंड की प्रतीक्षा करेगा, जिसके जॉइन () विधि को बुलाया गया था।
दोनों मामलों में 500 मिलीसेकंड के बाद, धागे चलते रहेंगे।
प्रतीक्षा (500) और नींद (500) में क्या अंतर है?
स्लीप (500) को थ्रेड पर कहा जाता है, प्रतीक्षा (500) को उस ऑब्जेक्ट पर एक सिंक्रनाइज़ ब्लॉक के अंदर कहा जाता है, जिस पर यह ब्लॉक सिंक्रनाइज़ किया गया है।
जब नींद (500) कहा जाता है, तो वर्तमान धागा 500 मिलीसेकंड तक इंतजार करेगा, फिर दौड़ना जारी रखें।
जब आप प्रतीक्षा (500) कहते हैं, तो वर्तमान धागा सिंक्रनाइज़ ऑब्जेक्ट पर लॉक जारी करेगा और 500 मिलीसेकंड के लिए सो जाएगा।
पैदावार () विधि कहा जाता है जब धागा किस राज्य में जाएगा?
जब उपज () विधि कहा जाता है, तो वर्तमान धागा "अपनी बारी को छोड़ देता है" और जावा तुरंत अगले धागे पर स्विच करता है। रनिंग स्टेट से थ्रेड तैयार अवस्था में जाता है। रनिंग और रेडी स्टेट्स RUNNABLE स्टेट के लिए सबस्टेशन हैं।
धागा वर्ग
थ्रेड क्लास System.Threading नामस्थान में सभी प्रकार का सबसे बुनियादी है। यह वर्ग एक विशिष्ट AppDomain के भीतर दिए गए निष्पादन पथ के चारों ओर एक वस्तु-उन्मुख आवरण का प्रतिनिधित्व करता है। यह प्रकार कई विधियों (स्थैतिक और उदाहरण-स्तर दोनों) को भी परिभाषित करता है जो आपको वर्तमान AppDomain के भीतर नए थ्रेड बनाने और एक विशिष्ट थ्रेड को निलंबित करने, रोकने और नष्ट करने की अनुमति देता है। मुख्य स्थैतिक सदस्यों की एक सूची नीचे दी गई है:
CurrentContextयह केवल पढ़ने के लिए संपत्ति संदर्भ देता है जिसमें धागा वर्तमान में चल रहा है
CurrentThreadयह केवल पढ़ने के लिए संपत्ति वर्तमान में निष्पादित थ्रेड का संदर्भ देता है
GetDomain (), GetDomainID () नींद ()यह विधि एक निश्चित समय के लिए वर्तमान थ्रेड को रोकती है
थ्रेड क्लास कई उदाहरण स्तर के तरीकों का भी समर्थन करता है, जिनमें से कुछ नीचे दी गई तालिका में वर्णित हैं। एक सक्रिय धागे को रद्द करना या रोकना आमतौर पर एक बुरा विचार माना जाता है। जब आप ऐसा करते हैं, तो एक मौका होता है (यद्यपि छोटा) कि एक धागा अपने कार्यभार को लीक कर सकता है जब वह परेशान या बाधित होता है।
उदाहरण स्तर के सदस्य | नियुक्ति |
जीवित है | एक बूलियन मान लौटाता है जो दर्शाता है कि क्या धागा शुरू हो गया है (और अभी तक बाधित या रद्द नहीं हुआ है) |
IsBackground | यह थ्रेड "बैकग्राउंड" है या नहीं यह इंगित करने वाला मान प्राप्त होता है या नहीं (नीचे और अधिक विवरण में) |
नाम | आपको स्ट्रीम के लिए एक अनुकूल टेक्स्ट नाम सेट करने की अनुमति देता है |
प्राथमिकता | किसी थ्रेड की प्राथमिकता देता है या सेट करता है, जो थ्रेडपैरिटी एन्यूमरेशन से एक वैल्यू हो सकता है |
ThreadState | इस थ्रेड की स्थिति हो जाती है, जिसे थ्रेडस्टेट गणन से एक मान सौंपा जा सकता है |
गर्भपात () | सीएलआर को निर्देश देता है कि थ्रेड को जल्द से जल्द निरस्त किया जाए |
रुकावट () | रुकावट (यानी निलंबित) एक निर्दिष्ट टाइमआउट अवधि के लिए वर्तमान धागा |
सम्मिलित हों () | कॉलिंग थ्रेड को तब तक ब्लॉक करता है जब तक कि निर्दिष्ट थ्रेड (जिसमें ज्वाइन () कहा जाता है) पूरा हो जाता है |
बायोडाटा () | पहले से निलंबित धागे को फिर से शुरू करता है |
शुरू () | सीएलआर को जल्द से जल्द धागा शुरू करने का निर्देश देता है |
सस्पेंड () | धागे को निलंबित कर देता है। यदि थ्रेड पहले से ही निलंबित है, तो सस्पेंड () का कोई प्रभाव नहीं है |
वर्तमान धारा के बारे में आंकड़े प्राप्त करना
याद रखें कि निष्पादन योग्य विधानसभा का प्रवेश बिंदु (यानी मुख्य () विधि) निष्पादन के प्राथमिक धागे पर चलता है। थ्रेड प्रकार के मूल उपयोग को समझाने के लिए, मान लें कि आपके पास एक नया कंसोल एप्लिकेशन है। जैसा कि आप जानते हैं, स्थैतिक Thread.CurrentThread गुण थ्रेड ऑब्जेक्ट को पुनर्प्राप्त करता है जो वर्तमान में चल रहे थ्रेड का प्रतिनिधित्व करता है। वर्तमान स्ट्रीम प्राप्त करने के बाद, आप इसके बारे में विभिन्न आँकड़े प्रदर्शित कर सकते हैं:
सिस्टम का उपयोग करना; System.Collections.Generic का उपयोग कर; System.Linq का उपयोग करना; System.Text का उपयोग कर; System.Threading का उपयोग करना; नामस्थान ConsoleApplication1 (क्लास प्रोग्राम (स्टेटिक शून्य मेन)) (Console.Title \u003d "(! LANG): मुख्य प्रोग्राम थ्रेड के बारे में जानकारी!"; Thread thread = Thread.CurrentThread; thread.Name = "MyThread"; Console.WriteLine(@"Имя домена приложения: {0} ID контекста: {1} Имя потока: {2} Запущен ли поток? {3} Приоритет потока: {4} Состояние потока: {5}", Thread.GetDomain().FriendlyName, Thread.CurrentContext.ContextID, thread.Name, thread.IsAlive, thread.Priority, thread.ThreadState); Console.ReadLine(); } } }!}
जबकि यह कोड अधिक या कम स्पष्ट है, ध्यान दें कि थ्रेड वर्ग नाम नामक एक संपत्ति रखता है। यदि आप इसके मूल्य को स्पष्ट रूप से निर्धारित नहीं करते हैं, तो नाम एक रिक्त स्ट्रिंग लौटाएगा। एक विशिष्ट थ्रेड ऑब्जेक्ट के लिए एक अनुकूल नाम असाइन करना डीबगिंग को बहुत सरल कर सकता है। विज़ुअल स्टूडियो 2010 में डिबगिंग सत्र के दौरान, आप डिबग -\u003e विंडोज -\u003e थ्रेड्स मेनू आइटम का चयन करके थ्रेड्स विंडो खोल सकते हैं।
ध्यान दें कि थ्रेड प्रकार प्राथमिकता नामक एक संपत्ति को परिभाषित करता है। डिफ़ॉल्ट रूप से, सभी धाराओं में सामान्य स्तर का प्राथमिकता स्तर होता है। हालाँकि, इसे थ्रेड के जीवन चक्र में किसी भी बिंदु पर थ्रेड.पायरिटी प्रॉपर्टी और इसके संबंधित सिस्टम का उपयोग करके बदला जा सकता है। थ्रेडिंग। थ्रेडपैरिटी एन्यूमरेशन:
सार्वजनिक एनम थ्रेडपैरिटी (सबसे निचला, निचला, सामान्य, // डिफ़ॉल्ट मान। उपरोक्त असामान्य, उच्चतम)
थ्रेड का प्राथमिकता स्तर डिफ़ॉल्ट (थ्रेडपैरिटी.नॉर्मल) के अलावा किसी अन्य मान पर सेट करते समय, ध्यान रखें कि यह थ्रेड शेड्यूलर थ्रेड्स के बीच स्विच करने के तरीके पर प्रत्यक्ष नियंत्रण प्रदान नहीं करता है। वास्तव में, एक थ्रेड का प्राथमिकता स्तर एक थ्रेड के कार्यों के महत्व के रूप में संकेत के साथ सीएलआर प्रदान करता है। इस प्रकार, थ्रेडपैरिटी के साथ एक धागा। उच्च प्राथमिकता प्राप्त करने के लिए आवश्यक नहीं है।
मान लें कि आप एक पाइपलाइन लिख रहे हैं जिसमें 2 धागे, एक सामान्य बफर, प्रक्रिया डेटा का उपयोग कर रहे हैं। निर्माता थ्रेड इस डेटा को बनाता है, और उपभोक्ता थ्रेड इसे संसाधित करता है (निर्माता - उपभोक्ता समस्या)। निम्नलिखित कोड सबसे सरल मॉडल है: std :: थ्रेड के साथ हम एक उपभोक्ता थ्रेड को स्पॉन करते हैं, और हम मुख्य थ्रेड में डेटा बनाते हैं।
शून्य उपज () (// एक कार्य बनाते हैं और इसे कतार में डालते हैं) शून्य खपत () (// कतार से डेटा पढ़ते हैं और इसे प्रोसेस करते हैं) इंट मेन (इंट, चार **) (एसटीडी :: थ्रेड थ्रेड थ्रू (उपभोग); // जनरेट) उपज () स्ट्रीम; // प्रसंस्करण के लिए डेटा बनाएं। थिऑन (); // खपत की प्रतीक्षा करें () रिटर्न 0 को समाप्त करने के लिए फ़ंक्शन;)
आइए दो थ्रेड को सिंक्रनाइज़ करने के लिए तंत्र को छोड़ दें, और मुख्य () फ़ंक्शन पर ध्यान दें। यह अनुमान लगाने की कोशिश करें कि इस कोड में क्या गलत है और इसे कैसे ठीक किया जाए?
मान लें कि खपत () फ़ंक्शन अपवाद फेंक रहा है। चूंकि यह अपवाद बच्चे के धागे पर फेंका गया है, आप इसे मुख्य धागे पर पकड़ नहीं सकते और संभाल नहीं सकते। यदि चाइल्ड थ्रेड के स्टैक के विस्तार के दौरान कोई उपयुक्त अपवाद हैंडलर नहीं मिलता है, तो std :: terminate () फ़ंक्शन को कहा जाएगा, जो डिफ़ॉल्ट रूप से एबॉर्ट () फ़ंक्शन को कॉल करेगा। दूसरे शब्दों में, यदि आप थ्रोट ऑब्जेक्ट द्वारा उत्पन्न थ्रेड में अपवाद को हैंडल नहीं करते हैं, तो प्रोग्राम एक त्रुटि के साथ बाहर निकल जाएगा।
उपज () फ़ंक्शन थोड़ा अधिक जटिल है। मान लें कि यह फ़ंक्शन एक अपवाद फेंकता है। पहली बात यह है कि एक कोशिश करने वाले ब्लॉक में मुख्य () बॉडी को लपेटना है:
प्रयास करें (std: थ्रेड थ्रोट (उपभोग); उत्पादन;); // एक थ्रो फेंकता है। (),;) पकड़ (...)
समस्या हल होने लगती है, लेकिन यदि आप इस कोड को चलाने का प्रयास करते हैं, तो कार्यक्रम वैसे भी दुर्घटनाग्रस्त हो जाएगा। ये क्यों हो रहा है? चलिए इसका पता लगाते हैं।
एसटीडी :: धागा
जैसा कि आप अब तक अनुमान लगा चुके हैं, समस्या पाइपलाइन से संबंधित नहीं है, लेकिन सिद्धांत रूप में मानक पुस्तकालय के धागे के सही उपयोग के लिए है। विशेष रूप से, निम्न सामान्य फ़ंक्शन समतुल्य है, और इसमें समान समस्याएं हैं:
शून्य रन (फ़ंक्शन)
हमारी समस्या को हल करने के लिए आगे बढ़ने से पहले, आइए संक्षेप में याद करें कि std :: thread कैसे काम करता है।
1) आरंभीकरण के लिए निर्माता:
खाका
जब std :: थ्रेड ऑब्जेक्ट को इनिशियलाइज़ किया जाता है, तो एक नया थ्रेड बनाया जाता है जिसमें fn फंक्शन की शुरुआत संभव तर्कों के साथ होती है। यदि इसे सफलतापूर्वक बनाया गया है, तो ऑब्जेक्ट का एक ठोस उदाहरण मूल सूत्र में इस थ्रेड का प्रतिनिधित्व करने के लिए शुरू होता है, और ऑब्जेक्ट में प्राप्य ध्वज को सेट किया जाता है।
याद रखें: joinable ~ एक ऑब्जेक्ट थ्रेड के साथ जुड़ा हुआ है।
2) हम उत्पन्न धागे के निष्पादन के अंत की प्रतीक्षा कर रहे हैं:
शून्य धागा :: जुड़ना ();
यह विधि बच्चे के समाप्त होने तक माता-पिता के धागे के आगे निष्पादन को रोकती है। सफल निष्पादन के बाद, थ्रेड ऑब्जेक्ट इसका प्रतिनिधित्व करना बंद कर देता है, क्योंकि हमारा धागा अब मौजूद नहीं है। जुड़ने योग्य ध्वज को मंजूरी दे दी गई है।
3) धारा से वस्तु को तुरंत "अलग" करें:
शून्य धागा :: डिटैच ();
यह एक गैर-अवरोधक विधि है। जुड़ने योग्य ध्वज को साफ कर दिया जाता है, और बच्चे के धागे को खुद पर छोड़ दिया जाता है और कुछ समय बाद बाहर निकल जाता है।
4) विध्वंसक:
धागा :: ~ धागा ();
संहारक वस्तु को नष्ट कर देता है। इसके अलावा, यदि इस ऑब्जेक्ट में शामिल होने योग्य झंडा है, तो std :: terminate () फ़ंक्शन को कहा जाता है, जो डिफ़ॉल्ट रूप से एबॉर्ट () फ़ंक्शन को कॉल करेगा।
ध्यान! यदि हम एक ऑब्जेक्ट और एक थ्रेड बनाते हैं, लेकिन कॉल ज्वाइन या अलग नहीं करते हैं, तो प्रोग्राम क्रैश हो जाएगा। सिद्धांत रूप में, यह तर्कसंगत है - यदि वस्तु अभी भी धारा के साथ जुड़ी हुई है, तो आपको इसके साथ कुछ करने की आवश्यकता है। बेहतर अभी तक, कुछ भी न करें और कार्यक्रम को समाप्त करें (कम से कम मानकों की समिति ने जो फैसला किया है)।
इसलिए, जब उत्पादन () फ़ंक्शन में कोई अपवाद होता है, तो हम थ्रोट ऑब्जेक्ट को नष्ट करने की कोशिश करते हैं, जो एक जुड़ने योग्य है।
सीमाएं
मानक समिति ने ऐसा करने का फैसला क्यों किया और अन्यथा नहीं? क्या विध्वंसक में जुड़ना () या टुकड़ी () को कॉल करना बेहतर नहीं होगा? यह बेहतर नहीं निकला। आइए इन दोनों मामलों को देखें।
मान लें कि हमारे पास एक join_thread क्लास है जो कॉल को इस तरह से अपने विध्वंसक में शामिल करती है:
Joining_thread :: ~ join_thread () (join ();)
फिर, अपवाद को संभालने से पहले, हमें बच्चे के थ्रेड के बाहर निकलने का इंतजार करना होगा, क्योंकि ज्वाइन () आगे प्रोग्राम के निष्पादन को अवरुद्ध करता है। क्या हुआ अगर ऐसा हुआ कि उत्पन्न धागा अनंत लूप में समाप्त हो गया?
शून्य उपभोग () (जबकि (1) (...)) ... कोशिश करना (ज्वाइनिंग_थ्रेड थ्रोट (उपभोग करना); थ्रो स्टैड :: अपवाद ();) कैच ... (...) / // जल्द ही नहीं हो सकता, या यहां तक \u200b\u200bकि कभी नहीं)
ठीक है, हमें पता चला कि विध्वंसक (जब तक आप सुनिश्चित नहीं हैं कि यह सही ईवेंट हैंडलिंग है) कॉल ज्वाइन नहीं करना बेहतर है, क्योंकि यह एक ब्लॉकिंग ऑपरेशन है। टुकड़ी () के बारे में क्या? विनाशकारी में इस गैर-अवरोधक विधि को क्यों नहीं कहा जाता है, जिससे मुख्य धागा जारी रहता है? मान लीजिए कि हमारे पास एक ऐसी कोचिंग_थ्रेड क्लास है।
लेकिन फिर हम एक ऐसी स्थिति में आ सकते हैं जहाँ स्पॉन्ड थ्रेड संसाधन का उपयोग करने की कोशिश करता है जो अब मौजूद नहीं है, जैसा कि निम्न स्थिति में है:
प्रयास करें (int data; detaching_thread th (उपभोग, और डेटा); // इस मामले में उपभोग करने के लिए एक तर्क के रूप में int एक सूचक ले जाता है std :: अपवाद ()) पकड़ (...) (// अपवाद को सही ढंग से संभालना // उपभोग जारी है निष्पादित करें, लेकिन पहले से हटाए गए डेटा ऑब्जेक्ट को संदर्भित करता है)
इस प्रकार, मानक के रचनाकारों ने प्रोग्रामर को जिम्मेदारी को स्थानांतरित करने का फैसला किया - अंत में, वह बेहतर जानता है कि कार्यक्रम को ऐसे मामलों को कैसे संभालना चाहिए। इस सब के आधार पर, यह पता चलता है कि मानक पुस्तकालय सिद्धांत का खंडन करता है - जब एक एसटी :: थ्रेड बनाते समय, हमें स्वयं सही संसाधन प्रबंधन का ध्यान रखना चाहिए, अर्थात स्पष्ट रूप से जुड़ने या अलग होने का आह्वान करें। इस कारण से, कुछ प्रोग्रामर एसटीडी :: थ्रेड ऑब्जेक्ट्स का उपयोग करने के खिलाफ सलाह देते हैं। नए और डिलीट की तरह, std :: थ्रेड उनमें से उच्च-स्तरीय टूल बनाने की क्षमता प्रदान करता है।
फेसला
ऐसा ही एक उपकरण बूस्ट लाइब्रेरी से :: थ्रेड_जॉइनर क्लास का बूस्ट है। यह ऊपर के उदाहरण में हमारे join_thread से मेल खाता है। यदि आप धाराओं के साथ काम करने के लिए तीसरे पक्ष के पुस्तकालयों का उपयोग कर सकते हैं, तो ऐसा करना बेहतर है।