2016-02-12 7 views
5

हुक तरीकों में से सकारात्मक:थ्रेडपूलएक्सएटर के बाद ओवरराइडिंग विधि - कोई विपक्ष?

beforeExecute(Thread, Runnable) और afterExecute(Runnable, Throwable)

beforeExecute(Thread, Runnable) और afterExecute(Runnable, Throwable) तरीकों कि पहले और प्रत्येक कार्य के निष्पादन के बाद कहा जाता है। इन्हें निष्पादन पर्यावरण में हेरफेर करने के लिए उपयोग किया जा सकता है; उदाहरण के लिए, थ्रेडलोकल्स को पुन: प्रारंभ करना, आंकड़े एकत्र करना, या लॉग प्रविष्टियां जोड़ना

मैं बिना किसी अपवाद को संभालने के लिए कस्टम ThreadPoolExecutor का उपयोग कर रहा हूं। मैं Runnable और Callable में ब्लॉक जोड़ सकता हूं लेकिन एक परिदृश्य मानता हूं जहां आप इन ब्लॉकों को प्रासंगिक Runnable और कॉल करने योग्य कार्यों में जोड़ने के लिए डेवलपर को मजबूर नहीं कर सकते हैं।

यह CustomThreadPoolExecutor, ओवरराइड करता है afterExecute() के रूप में नीचे ThreadPoolExecutor में विधि (मैं सौंपा है शून्य करने के लिए चर ख मूल्य अंकगणित अपवाद अनुकरण करने के लिए।

import java.util.concurrent.*; 
import java.util.*; 

class CustomThreadPoolExecutor extends ThreadPoolExecutor { 

    public CustomThreadPoolExecutor() { 
     super(1,10,60,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(1000)); 
    } 

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


public class CustomThreadPoolExecutorDemo{ 

    public static void main(String args[]){ 
     System.out.println("creating service"); 
     //ExecutorService service = Executors.newFixedThreadPool(10); 
     CustomThreadPoolExecutor service = new CustomThreadPoolExecutor(); 
     service.submit(new Runnable(){ 
       public void run(){ 
        int a=4, b = 0; 
        System.out.println("a and b="+a+":"+b); 
        System.out.println("a/b:"+(a/b)); 
        System.out.println("Thread Name in Runnable after divide by zero:"+Thread.currentThread().getName()); 
       } 
      }); 
     service.shutdown(); 
    } 
} 

submit() के बाद से ढांचे में अपवाद को छुपाता है, मैं करने के लिए afterExecute() विधि अधिरोहित है पकड़ अपवाद।

इस विधि में, मैं नीचे बयान के साथ कॉल को अवरुद्ध जोड़ा

Object result = ((Future<?>) r).get(); 

वर्तमान में मेरे पास 1000 के रूप में कतार क्षमता के साथ 10 धागे हैं। मान लें कि मेरा Runnable पूरा होने में 5 सेकंड लगते हैं।

afterExecute() विधि ओवरराइड करके, क्या मैं इस प्रदर्शन के साथ किसी भी प्रदर्शन ओवरहेड या किसी भी विपक्ष को लेकर हूं?

+2

में देख सकते हैं प्रदर्शन के बारे में अनुमान एक अच्छी बात है, बस बेंचमार्क के साथ और ओवरराइड के बिना कोड नहीं है और जाँच अगर वहाँ प्रासंगिक परिवर्तन कर रहे हैं। http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java – Jack

उत्तर

1

नहीं, आपकी अवरुद्ध कॉल एक ओवरहेड लाने नहीं होगा, पहले ही पूरा हो क्योंकि काम है अपनी निष्पादन और status >= NORMAL है के रूप में आप void runWorker(Worker w)

beforeExecute(wt, task); 
Throwable thrown = null; 
try { 
    task.run(); 
} catch (RuntimeException x) { 
    thrown = x; throw x; 
} catch (Error x) { 
    thrown = x; throw x; 
} catch (Throwable x) { 
    thrown = x; throw new Error(x); 
} finally { 
    afterExecute(task, thrown); 
} 
+0

लेकिन कुछ बार, मेरा get() परिदृश्यों में अवरुद्ध हो रहा है जब मेरे पास इंटर सर्विस संचार समस्याएं हैं (service.submit() और future.get() पर कॉल करें) –

+0

हां, 'get() 'ब्लॉक कर सकता है, लेकिन विधि' निष्पादन के बाद ' रननेबल आर, थ्रोबल टी) 'संरक्षित है और (यदि आपने 'फ्यूचरटास्क' सेमेन्टिक्स नहीं बदला है) तो कार्य पूरा होने के बाद 'थ्रेडपूल एक्स्सेलर' _only_ में कहा जाता है। – dezhik

1

बेहतर समाधान है, भविष्य पर पकड़ submit() से लौटे और फिर आप अपने मुख्य थ्रेड में अपवाद संभाल कर सकते हैं बजाय निष्पादक हैकिंग आप के लिए उसे प्रिंट करने के लिए।

एक अन्य विकल्प एक आम आधार Runnable जो अपवाद हैंडलिंग है कि आप की इच्छा को लागू करता है, उदाहरण के लिए उपयोग करने के लिए होगा:

public abstract class BaseRunnable implements Runnable { 
    public final run() { 
    try { 
     runImpl(); 
    } catch(Throwable t) { 
     t.printStackTrace(); 
    } 
    } 
    protected abstract runImpl() throws Exception; 
} 
+0

यह 'फ़्यूचरटास्क' के साथ काम नहीं करेगा जो अपवाद को पकड़ता है और 'सेट अपवाद)); 'और' रद्दीकरण अपवाद 'के साथ भी काम नहीं करेगा। अपवाद हमेशा पकड़ा जाएगा। – dezhik

+0

लेकिन इस मामले में, future.get() मुख्य थ्रेड ब्लॉक करता है। –

+0

@dezthink: यदि आप मुख्य थ्रेड में कोड नीचे जोड़ते हैं तो भी कॉल करने योग्य काम करेगा (मैंने इसे पहले किया है (एक्सेक्यूट दृष्टिकोण के बाद ओवरड करने से पहले): भविष्य।कोशिश करें() पकड़ {} पकड़ {} ब्लॉक –

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