ThreadPoolExecutor
1. try-cahch手动捕获异常
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
fixedThreadPool.execute(() -> {
try {
System.out.println("开始执行业务逻辑");
throw new RuntimeException();
} catch (Exception e) {
//处理出问题的线程
}
});
TimeUnit.SECONDS.sleep(10);
2. submit方法执行,获得Future对象,在获取返回值接受异常
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
Future<Object> future = fixedThreadPool.submit(() -> {
System.out.println("开始执行业务逻辑");
throw new RuntimeException();
});
try {
Object o = future.get();
} catch (Exception e) {
//处理异常
e.printStackTrace();
}
TimeUnit.SECONDS.sleep(10);
3. 重写线程池的afterExcute方法
下面的代码的task.run();就是执行具体的业务代码的地方,这里如果抛出异常就会执行afterExecute方法,所以就可以重写这个方法,来实现处理异常
final void runWorker(Worker w) {
//省略前面的代码
try {
beforeExecute(wt, task);
try {
task.run();
afterExecute(task, null);
} catch (Throwable ex) {
afterExecute(task, ex);
throw ex;
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
3.1 先自定义一个线程池
class MyExecutors extends ThreadPoolExecutor {
public MyExecutors(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
//重点就是重写这个方法
@Override
protected void afterExecute(Runnable r, Throwable t) {
if (!Objects.isNull(t)) {
System.out.println("处理异常");
}
}
}
3.2 创建自己的线程池
MyExecutors myExecutors = new MyExecutors(1, 1, 1, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
myExecutors.execute(() -> {
System.out.println("开始执行业务逻辑");
throw new RuntimeException();
});
TimeUnit.SECONDS.sleep(10);
4 设置线程的UncaughtExceptionHandler方法
Thread对象提供了**setUncaughtExceptionHandler方法用来获取线程中产生的异常**
4.1创建自己的线程工厂类
class MyThreadFactory extends DefaultThreadFactory {
public MyThreadFactory(String poolName) {
super(poolName);
}
@Override
public Thread newThread(Runnable r) {
Thread thread = super.newThread(r);
//设置要使用的线程的异常处理器
thread.setUncaughtExceptionHandler((t, e) -> {
System.out.println("出现错误2");
});
return thread;
}
}
4.2 创建线程池
//这里传入自己定义的线程工厂对象
ExecutorService executorService = Executors.newFixedThreadPool(10, new MyThreadFactory("pool"));
executorService.execute(() -> {
System.out.println("开始执行业务逻辑");
throw new RuntimeException();
});
TimeUnit.SECONDS.sleep(10);
ScheduledExecutorService
try-catch:还是可以使用
ScheduledExecutorService:毕竟是用来做延时任务和定时任务的,Future我觉得就不太好了。
UncaughtExceptionHandler:我也不知道为什么不行
afterExcute:不行的,下面细说
- 虽然说ScheduledExecutorService底层是ThreadPoolExecutor
- 但是ThreadPoolExecutor是将你传入的lambda表达式是直接执行的run方法执行业务逻辑的,但是ScheduledExecutorService是重新封装的一个RunnableScheduledFuture对象,然后是将任务放入该对象的callable成员变量中,然后重写了run方法,也就是下面这个样子
public void run() {
if (!canRunInCurrentRunState(this))
cancel(false);
//延时任务
else if (!isPeriodic())
super.run();
//定时任务
else if (super.runAndReset()) {
//设置下一次执行的时间
setNextRunTime();
//重新入队
reExecutePeriodic(outerTask);
}
}
}
- 然后在进入具体的执行代码,这里已经捕获了代码然后执行setException方法,所以就可以重写这个方法,实现异常处理
protected boolean runAndReset() {
//省略前面的代码
//这里是该线程的状态
int s = state;
try {
Callable<V> c = callable;
if (c != null && s == NEW) {
try {
//这里才是执行具体的业务逻辑
c.call(); // don't set result
ran = true;
} catch (Throwable ex) {
//然后在这里捕获了异常,所以说afterExecute方法是根本执行不到
//里面还会改变线程的状态
setException(ex);
}
}
} finally {
runner = null;
s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
//一旦出现异常这里就会返回false,也就不会重新入队了
return ran && s == NEW;
}
自定义FutureTask
class MyFutereTask extends FutureTask {
public MyFutereTask(Callable callable) {
super(callable);
}
//重点就是重写这个方法
@Override
protected void setException(Throwable t) {
super.setException(t);
System.out.println("异常处理");
}
}
创建线程池
ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
MyFutereTask myFutereTask = new MyFutereTask(() -> {
System.out.println(3);
throw new RuntimeException();
});
pool.scheduleAtFixedRate(myFutereTask, 0, 1, TimeUnit.SECONDS);