Overriding ThreadPoolExecutor afterExecute method - any cons?

Advantages of the hook method:

beforeExecute(Thread, Runnable) and afterExecute(Runnable, Throwable)

beforeExecute(Thread, Runnable ) and afterExecute(Runnable, Throwable) , which are called before and after each task. They can be used to control the runtime; e.g. reinitializing ThreadLocals, collecting statistics, or adding log entries

I am using Custom ThreadPoolExecutor to handle uncaught exceptions. I can add try{} catch{} blocks to Runnable and Callable , but suppose a scenario in which you cannot force the developer to add these blocks to the corresponding Runnable and Callable tasks.

This CustomThreadPoolExecutor , overrides the afterExecute () method in ThreadPoolExecutor , as shown below (I assigned the value of the b Zero variable to simulate an arithmetic exception.

 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(); } } 

Since submit() hides an exception in the framework, I have an overridden afterExecute() method for catch Exception.

In this method, I added a blocking call with the instruction below

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

I currently have 10 threads with a queue size of 1000. Suppose my Runnable takes 5 seconds.

Overriding the afterExecute () method, are there any performance overheads or any disadvantages of this approach?

+5
source share
2 answers

No, your blocking call will not bring any overhead, because the task has already completed its execution and has status >= NORMAL , as you can see in 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); } 
+1
source

The best solution held in the future comes back with submit() , and then you can handle the exception in your main thread instead of hacking the executor to print it for you.

Another alternative could be to use a common Runnable database that implements the required exception handling, for example:

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

Source: https://habr.com/ru/post/1242888/


All Articles