2010-12-20 16 views
15

जावा थ्रेड में, 'रन' विधि 'चेक अपवाद' नहीं फेंक सकती है। मैं कोर जावा (वॉल्यूम 1) पुस्तक में इस पर आया था। क्या कोई इसके पीछे तर्क की व्याख्या कर सकता है?जावा थ्रेड: रन विधि चेक अपवाद फेंक नहीं सकता

+4

अपवाद कहां जाएगा? थ्रेड जो नए धागे को जन्म देता है तब से आगे बढ़ गया है। तो, नया धागा किस धागे को निकाल दिया गया था और भूल गए मूल धागे के अपवाद को "भेज" देगा? – chaotic3quilibrium

उत्तर

16

क्या कोई इसके पीछे तर्क की व्याख्या कर सकता है?

हां, क्योंकि run विधि में आपके द्वारा फेंक दिया गया कोई अपवाद JVM द्वारा सावधानी से अनदेखा किया जाएगा। इस प्रकार, इसे फेंकना शायद एक गलती है (जब तक आपके पास थ्रेड के लिए विशिष्ट अपवाद हैंडलर न हो, तब तक the docs देखें)। संभावित रूप से गलत व्यवहार को उत्तेजित करने का कोई कारण नहीं है।

या, उदाहरण के साथ।

class MyThread extends Thread { 
    public void run() { 
     throw new RuntimeException(); 
    } 
} 

... 

new MyThread().start(); 
// here thread dies silently with no visible effects at all 

संपादित

क्यों नहीं माता पिता धागा 'पकड़' पैदा 'बच्चे' धागे से अपवाद?

@ chaotic3quilibrium पहले से ही अपने टिप्पणी में उल्लेख किया गया है नहीं क्यों: क्योंकि माता पिता धागा संभावना पहले से ही पर ले जाया गया है।

new MyThread().start(); // launch thread and forget 

// 1000 lines of code further... 
i = i + 1; // would you like exception from child thread to be propagated here? 
+0

क्या आप 'रन' में अपवादों को अनदेखा कर JVM के पीछे तर्क को समझा सकते हैं? –

+0

@ मार्टिन्हो यह और क्या कर सकता है? आत्महत्या विकल्प भी बदतर लगता है: आप एक थ्रेड के कारण पूरे एप्लिकेशन को क्रैश नहीं करना चाहते हैं। –

+4

बेवकूफ अनदेखी शायद भ्रामक है। अपवाद को थ्रेड के UncaughtExceptionHandler द्वारा संभाला जाएगा, जिसका डिफ़ॉल्ट कार्यान्वयन थ्रेड को मारने से पहले System.err पर स्टैकट्रैक को डंप करेगा। क्यों के लिए: वीएम कैसे पता चलेगा कि इसके बजाय क्या करना है? – meriton

0

throws घोषणाएं विधियों के हस्ताक्षर का हिस्सा हैं। Runnable#run के लिए चेक अपवादों की अनुमति देने के लिए, उन्हें Runnable इंटरफ़ेस पर घोषित करना पड़ा और जब भी हम धागे शुरू करते हैं तो उन्हें try/catch करना था।

फिर, हम आमतौर पर run विधि को कॉल नहीं करते हैं, हम इसे अभी लागू करते हैं। हम start() एक थ्रेड और फिर, किसी भी तरह, run विधि कहा जाता है।

लेकिन सबसे स्पष्ट कारण:

try { 
    new Worker().start(); // now wait until run has finished 
} catch (SomeThreadException oops) { 
    // handle checked exception 
} 
0

कारण यह है कि अपवाद वापस फेंक दिया जाता है है: जब हम धागे शुरू करते हैं, हम आम तौर पर नहीं जाने तक प्रतीक्षा करना run विधि इस तरह अपवाद को पकड़ने के लिए बस समाप्त हो जाता है चाहता हूँ कॉलर के लिए। रन() विधि का कॉलर आपका कोड नहीं है। यह खुद ही थ्रेड है। तो यहां तक ​​कि अगर रन() अपवाद फेंकता है तो प्रोग्राम इसे पकड़ नहीं सकता है।

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

7

अपवाद को पकड़ने और इसे संभालने में क्या होगा? आइए मान लें कि रन विधि एक चेक अपवाद फेंक सकती है। तो फिर तुम इस तरह कोड लिख सकते हैं:

Thread myThread = new Thread(aRunnable); 
try{ 
    myThread.start(); 
} 
catch(Exception e){ 
    e.printStackTrace(); 
} 
//do other stuff 

लेकिन एक बार आप myThread.start फोन, नया थ्रेड पृष्ठभूमि में शुरू कर दिया है और मौजूदा धागा जारी है और कोशिश पकड़ बाहर निकल जाता है और अन्य सामग्री है। तो अगर myThread ने बाद में अपवाद फेंक दिया, तो आप इसे पकड़ नहीं सकते!

आपको क्या करना है run विधि के भीतर अपवाद के साथ सौदा करना है और उसके बाद संभवतः एक अन्य ऑब्जेक्ट को सूचित करने का एक तरीका है कि यह थ्रेड विफल हो गया है।

0

पिछले उत्तरों के लिए अधिक स्पष्ट समाधान यह है कि यदि आप एक चेक अपवाद फेंकते हैं, तो आप रननेबल इंटरफ़ेस में निर्दिष्ट अनुसार रन() को सही ढंग से कार्यान्वित नहीं कर रहे हैं।

यह भी संकलन नहीं होगा:

run() in TestClass cannot implement run() in java.lang.Runnable; 
overridden method does not throw java.lang.Exception 
1

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

try 
{ 
    threadB=new PurgeAbandonedCarts(); 
    threadB.start(); 
} 
catch (NullPointerException panic) 
{ 
    ... handle errors purging abandoned carts ... 
} 
try 
{ 
    processNewOrders(); 
} 
catch (NullPointerException panic) 
{ 
    ... handle problems in new orders ... 
} 
finally 
{ 
    ... clean up ... 
} 

तो हम छोड़ी गई कार्ट शुद्ध करने के लिए धागा शुरू। एक बार यह शुरू हो जाने के बाद, हम नए आदेशों को संसाधित करने के लिए आगे बढ़ते हैं। फिर थ्रेड बी एक शून्य सूचक अपवाद फेंकता है। क्या इसे थ्रेड बी से जुड़े कैच ब्लॉक द्वारा पकड़ा जाना चाहिए, या नया ऑर्डर प्रोसेस करने से जुड़ा हुआ है?

यदि यह नए ऑर्डर कैच में जाता है, तो संभव है कि यहां किसी भी कोड के पास थ्रेड बी के साथ समस्याओं को साफ करने के लिए कुछ भी नहीं है। यह सही जवाब नहीं हो सकता है।

यदि आप थ्रेड बी से जुड़े एक कहते हैं, तो इसका मतलब है कि नए आदेशों के प्रसंस्करण के दौरान, नियंत्रण अचानक यंक हो सकता है और थ्रेड बी कैच ब्लॉक को आजमाया जा सकता है। लेकिन फिर नए आदेशों को संसाधित करने के लिए क्या खुशी हुई? क्या हम बस बीच में रुकते हैं? क्या हम आखिरकार ब्लॉक भी नहीं मारा? और जब हम कर लेंगे, तो क्या हम फिर से नए आदेशों को संसाधित करने के लिए निष्पादन करते हैं और गिरते रहते हैं? क्या हम दो बार आदेश संसाधित करते हैं? यह या तो सही जवाब नहीं हो सकता है।

इस प्रकार, अगर कोई अपवाद फेंकता है तो कहीं भी नहीं जाना है। ऐसा करने के लिए एकमात्र तार्किक बात यह है कि रन विधि को किसी भी अपवाद को फेंक दिया जाता है, और उन्हें नए धागे के भीतर संभाला जाता है।

संबंधित मुद्दे