為執行緒池中的每個執行緒設定UncaughtExceptionHandler
阿新 • • 發佈:2019-01-26
參考了《java併發程式設計實戰》P134內容
每當執行緒池需要建立一個執行緒時,都是通過呼叫執行緒工廠方法來完成的,預設的執行緒工廠方法將建立一個新的、非守護的執行緒,並且不包好特殊的配置資訊。
如果你希望線上程執行之前、之後、或者執行中如果發生異常等情況作一些人工干預的話,可以自定義執行緒工廠。
示例:
import java.util.concurrent.atomic.*; import java.util.logging.*; public class MyAppThread extends Thread { public static final String DEFAULT_NAME = "MyAppThread"; private static final AtomicInteger created = new AtomicInteger(); private static final AtomicInteger alive = new AtomicInteger(); private static final Logger log = Logger.getAnonymousLogger(); public MyAppThread(Runnable r) { this(r, DEFAULT_NAME); } public MyAppThread(Runnable runnable, String name) { super(runnable, name + "-" + created.incrementAndGet()); this.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { log.log(Level.SEVERE, "UNCAUGHT in thread " + t.getName(), e); } }); } public void run() { System.out.println("Created " + getName()); try { alive.incrementAndGet(); super.run(); } finally { alive.decrementAndGet(); System.out.println("Exiting " + getName()); } } public static int getThreadsCreated() { return created.get(); } public static int getThreadsAlive() { return alive.get(); } } import java.util.concurrent.*; public class MyThreadFactory implements ThreadFactory { private final String poolName; public MyThreadFactory(String poolName) { this.poolName = poolName; } public Thread newThread(Runnable runnable) { return new MyAppThread(runnable, poolName); } } 測試類: import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class MyThreadFactoryClient { public static void main(String[] args) { ExecutorService pool = new ThreadPoolExecutor(3, 3, 0L, TimeUnit.MICROSECONDS, new LinkedBlockingQueue<Runnable>(), new MyThreadFactory("ZJH")); for (int i = 0; i < 10; i++) { pool.execute(new MyThread("" + i)); } pool.shutdown(); } static class MyThread extends Thread { public String name; public MyThread(String name) { this.name = name; } public void run() { if("5".equals(name)){ throw new NullPointerException("5 is null"); } System.out.println("Thread-" + name + " is running....."); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } 擴充套件ThreadPoolExecutor : import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.util.logging.*; public class TimingThreadPool extends ThreadPoolExecutor { public TimingThreadPool() { super(1, 1, 0L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); } private final ThreadLocal<Long> startTime = new ThreadLocal<Long>(); private final AtomicLong numTasks = new AtomicLong(); private final AtomicLong totalTime = new AtomicLong(); protected void beforeExecute(Thread t, Runnable r) { super.beforeExecute(t, r); System.out.println(String.format("Thread %s: start %s", t, r)); startTime.set(System.nanoTime()); } protected void afterExecute(Runnable r, Throwable t) { try { long endTime = System.nanoTime(); long taskTime = endTime - startTime.get(); numTasks.incrementAndGet(); totalTime.addAndGet(taskTime); System.out.println(String.format("Thread %s: end %s, time=%dns", t, r, taskTime)); } finally { super.afterExecute(r, t); } } protected void terminated() { try { System.out.println(String.format("Terminated: avg time=%dns", totalTime.get() / numTasks.get())); } finally { super.terminated(); } } public static void main(String[] args) { TimingThreadPool pool = new TimingThreadPool(); pool.execute(new Runnable(){ public void run() { System.out.println(Thread.currentThread().getName()); try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } } }); pool.shutdown(); } }