2010-08-24 18 views
19

में अपवाद को पकड़ने के लिए है कि FutureTask जावा 1.6 (और ग्रहण से) पर एक Executors.newCachedThreadPool() में चल खोजने के बाद Runnable.run() विधि में अपवाद निगल, मैं फेंक/कैच जोड़े बिना इन को पकड़ने के लिए एक तरह से साथ आने के लिए कोशिश की है मेरे सभी Runnable कार्यान्वयन के लिए।कैसे FutureTask

एपीआई पता चलता है कि अधिभावी FutureTask.setException() इस में मदद करनी चाहिए:, इसके कारण के रूप में दिया फेंकने योग्य के साथ एक ExecutionException रिपोर्ट करने के लिए जब तक कि इस भविष्य को पहले से ही स्थापित किया गया है या रद्द कर दिया गया

कारण यह भविष्य। इस पद्धति को गणना की विफलता पर रन विधि द्वारा आंतरिक रूप से बुलाया जाता है।

हालांकि इस विधि के नाम से जाना प्रतीत नहीं होता है (डिबगर के साथ चल रहा से पता चलता अपवाद FutureTask द्वारा पकड़ा जाता है, लेकिन setException कहा जाता है नहीं है)। मैं मेरी समस्या पुन: पेश करने के बाद कार्यक्रम में लिखा है:

public class RunTest { 
    public static void main(String[] args) { 
     MyFutureTask t = new MyFutureTask(new Runnable() { 

      @Override 
      public void run() { 
       throw new RuntimeException("Unchecked exception"); 

      } 
     }); 

     ExecutorService service = Executors.newCachedThreadPool(); 
     service.submit(t); 
    } 
} 

public class MyFutureTask extends FutureTask<Object> { 

    public MyFutureTask(Runnable r) { 
     super(r, null); 
    } 

    @Override 
    protected void setException(Throwable t) { 
     super.setException(t); 
     System.out.println("Exception: " + t); 
    } 
} 

मेरा मुख्य सवाल यह है: मैं एक FutureTask में फेंक दिया अपवाद कैसे पकड़ कर सकते हैं? setException क्यों नहीं कहा जाता है?

मैं यह भी जानना चाहता हूं कि Thread.UncaughtExceptionHandler तंत्र का उपयोग FutureTask द्वारा क्यों नहीं किया जाता है, क्या इसके लिए कोई कारण है?

+1

'setException' का अच्छी तरह से उपयोग किया जाता है। मैंने आपके कोड को कॉपी किया है और यह काम करता है। कार्य पर 'get()' विधि को कॉल करते समय आप 'निष्पादन अपवाद' की कोशिश करने का प्रयास भी कर सकते हैं। – Kru

+0

कॉल करने योग्य/भविष्य कॉम्बो का उपयोग करने का गलत तरीका। Future.get() विधि आपको निष्पादन अपवाद में लपेटा गया अपवाद प्रदान करता है। – Bhushan

उत्तर

20

setException शायद ओवरराइडिंग के लिए नहीं बनाया गया है, लेकिन आपको परिणाम को अपवाद में सेट करने के लिए प्रदान किया जाता है, आवश्यकता उत्पन्न होनी चाहिए।

public class MyFutureTask extends FutureTask<Object> { 

    public MyFutureTask(Runnable r) { 
     super(r, null); 
    } 

    @Override 
    protected void done() { 
     try { 
      if (!isCancelled()) get(); 
     } catch (ExecutionException e) { 
      // Exception occurred, deal with it 
      System.out.println("Exception: " + e.getCause()); 
     } catch (InterruptedException e) { 
      // Shouldn't happen, we're invoked when computation is finished 
      throw new AssertionError(e); 
     } 
    } 
} 
+0

यह काम किया, धन्यवाद। – Thirler

+0

हम ExecutionException ऑब्जेक्ट से स्टेटस कोड कैसे खींच सकते हैं? – Min2

+0

@ Min2 अगर आप अपवाद चाहते हैं जो 'निष्पादन अपवाद' का कारण बनता है, तो आप println कथन में 'getCause()' का उपयोग कर सकते हैं। – gustafc

2

मैंने FutureTask के स्रोत कोड को देखा है और यह नहीं मिला कि setException कहां जा रहा है।
FutureTask.Sync (FutureTask की आंतरिक श्रेणी) से innerSetException विधि है जिसे रन विधि द्वारा Throwable फेंकने के मामले में कहा जा रहा है। इस विधि को setException में भी बुलाया जा रहा है।
तो यह जवाडोक की तरह सीम सही नहीं है (या समझने में बहुत मुश्किल है ...)।

+0

बहुत धीमे सूरज कीड़े डेटाबेस पर कुछ और देखने के बाद: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6464365 उचित रूप से यह 2006 से ज्ञात है और अभी भी तय नहीं है (घटना यह निश्चित रूप से तय की गई है) – Thirler

+1

@ थिल्डर - बग रिपोर्ट स्पष्ट रूप से कहती है कि यह जावा 7 ** ** में तय है। –

12

आप एक UncaughtExceptionHandler उपयोग करने की कोशिश है: क्या आप क्या करना चाहते done() विधि ओवरराइड और परिणाम प्राप्त करने की कोशिश है?

  • आपको UncaughtExceptionHandler इंटरफ़ेस को लागू करने की आवश्यकता है।
  • पूल थ्रेड के लिए UncaughtExceptionHandler सेट करने के लिए, Executor.newCachedThreadPool(ThreadFactory) कॉल में ThreadFactory प्रदान करें।
  • आप के माध्यम से setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

बनाया थ्रेड के लिए UncaughtExceptionHandler सेट कर सकते हैं ExecutorService.execute के साथ कार्य करें, क्योंकि केवल execute के साथ प्रस्तुत कार्यों से फेंका अपवाद न आया हुआ अपवाद हैंडलर बनाते हैं। ExecutorService.submit के साथ सबमिट किए गए कार्यों के लिए किसी भी फेंकने वाले अपवाद को कार्य के वापसी मूल्य का हिस्सा माना जाता है।एक कार्य के साथ प्रस्तुत प्रस्तुत एक अपवाद के साथ समाप्त होता है, यह जब Future.get बुला rethrown है, एक ExecutionException

+0

अच्छी पकड़! मैं गलती से 'execorService.submit' का उपयोग कर रहा था। – Gili

8

एक बहुत बेहतर समाधान में लिपटे: Java FutureTask completion check

जब आप futureTask.get() फोन गणना के परिणाम पुनः प्राप्त करने के लिए यह होगा अंतर्निहित Runnable/Callable अपवाद फेंकने पर अपवाद (निष्पादन अपवाद) फेंक दें।

ExecutionException.getCause() अपवाद वापस करेगा कि Runnable/Callable फेंक दिया गया।

Runnable/Callable रद्द कर दिया गया था, तो यह एक अलग अपवाद भी फेंक देगा।

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

  • कोई संबंधित समस्या नहीं^_^