2016-02-12 31 views
5

Plusy metod Hak:Zastępowanie ThreadPoolExecutor afterExecute method - jakiekolwiek minusy?

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

beforeExecute(Thread, Runnable) i afterExecute(Runnable, Throwable) metody, które nazywane są przed i po wykonaniu każdego zadania. Mogą one służyć do manipulowania środowiskiem wykonawczym; na przykład, ponowne zainicjowanie ThreadLocals, zbieranie statystyk lub dodawanie wpisów w logach

Używam Custom ThreadPoolExecutor do obsługi niezatrzonych wyjątków. Mogę dodać bloki try{} catch{} w Runnable i Callable, ale przyjmij scenariusz, w którym nie możesz zmusić programisty do dodania tych bloków w odpowiednich zadaniach Runnable i Callable.

to CustomThreadPoolExecutor, zastępuje afterExecute() Sposób ThreadPoolExecutor jak poniżej (I przypisaną wartość zmiennej B do zera, aby symulować arytmetyczną wyjątku.

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

Ponieważ submit() ukrywa wyjątku w kontekście I zastąpione afterExecute() metody Wyjątek haczyk.

W tej metodzie, dodałem blokowanie połączenia z poniższym oświadczeniem

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

Obecnie mam 10 wątków z kolejką o pojemności 1000. Załóżmy, że mój Runnable trwa 5 sekund.

Zastępując metodę afterExecute(), czy ponoszę jakiekolwiek obciążenie operacyjne LUB jakiekolwiek minusy z tym podejściem?

+2

odgadywanie o wydajności nie jest dobrą rzeczą, po prostu wzorzec kodu zi bez ręcznego i sprawdzić, czy istnieją odpowiednie zmiany. http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-mic-benchmark-in-java – Jack

Odpowiedz

1

Nie, rozmowa blokowanie nie przyniesie narzutu, ponieważ zadanie jest już zakończyła wykonanie i ma status >= NORMAL jak widać w 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

Ale czasami, moje get() blokuje się w scenariuszach, gdy mam problemy z komunikacją między usługami (service.submit() i wywołuję future.get()) –

+0

Tak, 'get()' może blokować, ale metoda 'afterExecute (Runnable r, Throwable t) 'jest chronione i (jeśli nie zmieniłeś semantyki" FutureTask ") jest wywoływane w' ThreadPoolExecutor' _only_ po wykonaniu zadania. – dezhik

1

lepszym rozwiązaniem, trzymaj się do przyszłości wrócił z submit() a następnie można obsłużyć wyjątek w głównym wątku zamiast hacking wykonawcę, aby wydrukować go dla Ciebie.

Inną alternatywą byłoby wykorzystanie wspólnej bazy Runnable który implementuje obsługę wyjątków, które pragną, np

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

Nie działałoby to z 'FutureTask's, który przechwytuje wyjątek i' setException (ex); 'a także nie działałby z' CancellationException'. Wyjątek zawsze zostanie złapany. – dezhik

+0

, ale w tym przypadku future.get() blokuje główny wątek. –

+0

@dezthink: Nawet Callable zadziała, jeśli dodasz poniższy kod w głównym wątku (zrobiłem to wcześniej (przed przepełnieniem po podejściu Execute): przyszłość.get() in try {} catch {} block –