1. 程式人生 > >為執行緒池中的每個執行緒設定UncaughtExceptionHandler

為執行緒池中的每個執行緒設定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();
 }
}