8

मैं ThreadPoolExecutor#afterExecute() विधि में कार्यकर्ता धागे द्वारा फेंकने वाले निष्पादन को संभालना चाहता हूं।ThreadPoolExecutor के बाद अपवाद() में अपवाद क्यों शून्य है?

public class MyExecutor extends ThreadPoolExecutor { 

    public static void main(String[] args) { 
     MyExecutor threadPool = new MyExecutor(); 
     Task<Object> task = new Task<>(); 
     threadPool.submit(task); 
    } 

    public MyExecutor() { 
     super(4, 20, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(4000)); 
    } 

    @Override 
    protected void afterExecute(Runnable r, Throwable t) { 
     super.afterExecute(r, t); 
     System.out.println("in afterExecute()"); 
     if (t != null) { 
      System.out.println("exception thrown: " + t.getMessage()); 
     } else { 
      System.out.println("t == null"); 
     } 
    } 

    private static class Task<V> implements Callable<V> { 

     @Override 
     public V call() throws Exception { 
      System.out.println("in call()"); 
      throw new SQLException("testing.."); 
     } 
    } 
} 

अगर मैं कोड चल रहा आउटपुट प्राप्त:

in call() 
in afterExecute() 
t == null 

पैरामीटर Throwable tnullafterExecute() में क्यों है वर्तमान में मैं इस कोड है? यह SQLException उदाहरण नहीं होना चाहिए?

उत्तर

7

यह वास्तव में व्यवहार की उम्मीद है।

तो गैर-शून्य, फेंकने योग्य ध्यान में न आया RuntimeException या त्रुटि है कि वजह से निष्पादन अचानक समाप्त करने के लिए है:

afterExecute जावाडोक का हवाला देते हुए।

इसका मतलब यह है फेंकने योग्य उदाहरण RuntimeException या Error, Exception नहीं जाँच की जाएगी। चूंकि SQLException एक चेक अपवाद है, इसलिए इसे afterExecute पर नहीं भेजा जाएगा।

वहाँ भी कुछ और यहाँ पर जा रहा (अभी भी जावाडोक के हवाले से) है:

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

अपने उदाहरण में, काम के लिए एक FutureTask में संलग्न है के बाद से आप एक Callable सबमिट कर रहे हैं, तो आप इस मामले में कर रहे हैं। यहां तक ​​कि RuntimeException फेंकने के लिए आप अपना कोड बदल सकते हैं, अगर afterExecute पर नहीं दिया जाएगा।

protected void afterExecute(Runnable r, Throwable t) { 
    super.afterExecute(r, t); 
    if (t == null && r instanceof Future) { 
     try { 
     Object result = ((Future) r).get(); 
     } catch (CancellationException ce) { 
      t = ce; 
     } catch (ExecutionException ee) { 
      t = ee.getCause(); 
     } catch (InterruptedException ie) { 
      Thread.currentThread().interrupt(); // ignore/reset 
     } 
    } 
    if (t != null) 
     System.out.println(t); 
} 
+0

इसे साफ़ करने के लिए धन्यवाद। तो सभी चेक अपवादों को ThreadPoolExecutor द्वारा निगलने जा रहे हैं? और सभी अपवाद हैंडलिंग कॉलबल # कॉल() में किया जाना चाहिए? –

+1

@ potato300 मेरा संपादन देखें, आपके विशिष्ट उदाहरण में कुछ और चल रहा है (जिसे मैंने पहले नहीं देखा था) – Tunaki

1

यह कर का एक वैकल्पिक तरीका है: जावाडोक इस से निपटने के लिए एक नमूना कोड है, जो मैं यहाँ प्रतिलिपि बनाई जा रही हूँ, संदर्भ के लिए देता है। से here

package com.autonomy.introspect.service; 

import java.sql.SQLException; 
import java.util.concurrent.*; 

public class MyExecutor extends ThreadPoolExecutor { 

    public static void main(String[] args) { 
     MyExecutor threadPool = new MyExecutor(); 
     Task<Object> task = new Task<Object>(); 
     Future<Object> futureTask = threadPool.submit(task); 
     try { 
      System.out.println(futureTask.get()); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } catch (ExecutionException e) { 
      System.out.println("exception thrown: " + e.getMessage()); 
     } 
    } 

    public MyExecutor() { 
     super(4, 20, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(4000)); 
    } 

    @Override 
    protected void afterExecute(Runnable r, Throwable t) { 
     super.afterExecute(r, t); 
     System.out.println("in afterExecute()"); 
     if (t != null) { 
      System.out.println("exception thrown: " + t.getMessage()); 
     } else { 
      System.out.println("t == null"); 
     } 
    } 

    private static class Task<V> implements Callable<V> { 

     @Override 
     public V call() throws Exception { 
      System.out.println("in call()"); 
      throw new SQLException("testing.."); 
     } 
    } 
} 

संकेत लेते हुए afterExecute के उपयोग के लिए एक अलग उद्देश्य के लिए है।

This class provides protected overridable beforeExecute(java.lang.Thread, 
java.lang.Runnable) and afterExecute(java.lang.Runnable, 
java.lang.Throwable) methods that are called before and after execution of 
each task. These can be used to manipulate the execution environment; for 
example, reinitializing ThreadLocals, gathering statistics, or adding log 
entries. Additionally, method terminated() can be overridden to perform any 
special processing that needs to be done once the Executor has fully 
terminated. 

If hook or callback methods throw exceptions, internal worker threads may 

बदले में विफल और अचानक समाप्त हो गया।

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