为线程池中的每个线程设置UncaughtExceptionHandler
参考了《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(); } }