2011-07-12 15 views
7

यह स्निपेट JCIP (ब्रायन गोएज़) से एक प्रविष्टि 6.15क्यों एक काम है कि एक थ्रेड पूल के धागे

f.get में भाग गया (की बाधा झंडा बहाल) InterruptedException और ExecutionException फेंकता है। अब, ये अपवाद भविष्य के लिए विशिष्ट हैं? मतलब भविष्य के प्रतिनिधित्व वाले विशिष्ट कार्य को बाधित किया गया था या आंतरिक अपवाद था।

प्रश्न -

  1. मैं क्यों बाधा का उपयोग कर बहाल करने की जरूरत है "Thread.currentThread() बीच में()।"? , क्योंकि मेरे काम में धागे के लिए बाधा झंडा नहीं है? यह थोड़ा उलझन में है।

  2. क्यों लंदन फेंकने योग्य अपवाद? अगर डाउनलोड इमेज में से कोई एक मुद्दा था, तो क्या हम यहां से डाउनलोड की गई अन्य डाउनलोड की गई छवियों को केवल फेंकने की प्रक्रिया नहीं कर सकते हैं और इस प्रकार शेष वायदा को संसाधित नहीं कर सकते हैं?

    package net.jcip.examples; 
    
    import java.util.*; 
    import java.util.concurrent.*; 
    import static net.jcip.examples.LaunderThrowable.launderThrowable; 
    
    /** 
    * Renderer 
    * <p/> 
    * Using CompletionService to render page elements as they become available 
    * 
    * @author Brian Goetz and Tim Peierls 
    */ 
    public abstract class Renderer { 
        private final ExecutorService executor; 
    
        Renderer(ExecutorService executor) { 
         this.executor = executor; 
        } 
    
        void renderPage(CharSequence source) { 
         final List<ImageInfo> info = scanForImageInfo(source); 
         CompletionService<ImageData> completionService = 
           new ExecutorCompletionService<ImageData>(executor); 
         for (final ImageInfo imageInfo : info) 
          completionService.submit(new Callable<ImageData>() { 
           public ImageData call() { 
            return imageInfo.downloadImage(); 
           } 
          }); 
    
         renderText(source); 
    
         try { 
          for (int t = 0, n = info.size(); t < n; t++) { 
           Future<ImageData> f = completionService.take(); 
           ImageData imageData = f.get(); 
           renderImage(imageData); 
          } 
         } catch (InterruptedException e) { 
          Thread.currentThread().interrupt(); 
         } catch (ExecutionException e) { 
          throw launderThrowable(e.getCause()); 
         } 
        } 
    
        interface ImageData { 
        } 
    
        interface ImageInfo { 
         ImageData downloadImage(); 
        } 
    
        abstract void renderText(CharSequence s); 
    
        abstract List<ImageInfo> scanForImageInfo(CharSequence s); 
    
        abstract void renderImage(ImageData i); 
    
    } 
    

उत्तर

1
  1. थ्रेड पूल के धागे पर बाधा नहीं होती है। बाधा एक बिंदु के लिए है जब भविष्य में आने के इंतजार के दौरान आपका वर्तमान धागा बाधित हो जाता है। उदाहरण के लिए, यदि आपने प्रोग्राम को किसी अन्य प्रोग्राम के लिए सुलभ बनाया है जो डाउनलोड को रद्द कर सकता है, तो Future.cancel (true) उस इंटरप्टेड अपवाद को उत्पन्न करेगा जिससे आप बाकी डेटा को साफ़ कर सकते हैं। और जैसा कि बोहेमियान ने उल्लेख किया है, बाधा उत्पन्न करने के लिए हमेशा सुरक्षित है।

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

+0

'त्रुटि' कुछ अप्राप्य होने वाला माना जाता है। 'StackOverflowError' के बारे में कैसे? ढेर शायद दूषित हो गया। 'InternalError' के बारे में कैसे? यह वीएम राज्य दूषित है। आप उन्हें पकड़ नहीं सकते हैं। –

+0

हाँ आप सही हैं। यही वह जगह है जहां मैं OutOfMemoryError के साथ जा रहा था।हालांकि लॉंडर विधि रनटाइम अपवादों को भी पुनर्स्थापित करेगी (कम से कम उदाहरण में) –

2

InterruptedException पकड़ने रखकर आप धागा है जिसमें आप चल रहे हैं तक पहुँचने से रुकावट को रोकने के कर रहे हैं। लेकिन आप इसे प्राप्त करना चाहते हैं, अगर कोई विशेष प्रसंस्करण हो तो थ्रेड को बाधा के मामले में करने की ज़रूरत है - आप यह नहीं बता सकते हैं, तो आप बेहतर इसे सुरक्षित खेलेंगे और इसे पार करने की अनुमति देंगे। आप कुछ प्रसंस्करण कर सकते हैं (साफ करने के लिए, आप जो कर रहे हैं उससे बाहर निकलें, आदि), लेकिन आपको इसे पास करना होगा। ऐसा करने का सबसे अच्छा तरीका Thread.currentThread().interrupt() पर कॉल करना है।

3

जब आप इंटरप्टेड एक्सेप्शन को बाधित करते हैं तो फ्लैग रीसेट हो जाता है और आपका धागा तकनीकी रूप से बाधित नहीं होता है। हालांकि, आपको नहीं पता कि कोड जो आपके कोड (या उसी थ्रेड में अन्य कोड) कहलाता है, को किसी भी अतिरिक्त इंटरप्ट हैंडलिंग की आवश्यकता होती है। इंटरप्ट() को कॉल करके आप फ्लैग को फिर से बढ़ाते हैं और प्रभावी रूप से बाकी एप्लिकेशन को कहते हैं "यह थ्रेड अभी भी बाधित है - यदि आवश्यक हो तो उस पर कार्य करें"।

उदाहरण पर विचार करें। आपको विधि को लूप से बुलाया जाता है जिसे थ्रेड बाधित होने पर समाप्त करना होगा। आपने अपवाद पकड़ा और यदि आप ध्वज नहीं उठाते हैं, तो लूप आवश्यकतानुसार समाप्त नहीं होगा।

+0

बस अधिक विवरण जोड़ने के लिए: जब जावा पुस्तकालयों में से कुछ अवरुद्ध विधियां 'इंटरप्टेड एक्सेप्शन' फेंकता है, तो थ्रेड का बाधित ध्वज गलत पर रीसेट हो जाता है। उदाहरण के लिए ['Thread.sleep()'] के दस्तावेज़ (http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#sleep%28long%29) या [' Object.wait() '] (http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait%28%29) –

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