目录
- 方案 1
- 方案 2
- 方案 3
- 方案 4
- 结论
方案 1
使用 execute
+ try-catch
记录异常
import Java.util.concurrent.*; public class ThreadPoolExceptionDemo { public static vwww.devze.comoid main(String[] args) { ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, 4, 10, TimeUnit.SECONDS, new LinkedblockingQueue<>(), new ThreadFactory() { private int count = 1; @Override public Thread newThread(Runnable r) { return new Thread(r, "custom-thread-" + count++); } }); executor.execute(() -> { try { System.out.println(Thread.currentThread().getName() + " 正在执行任务"); throw new RuntimeException("任务异常"); } catch (Exception e) { System.err.println("线程 " + Thread.currentThread().getName() + " 捕获异常: " + e.getMessage()); e.printStackTrace(); } }); executor.shutdown(); } }
方案 2
使用 submit + Future
submit()
方法返回 Future
,可以通过 get()
方法捕获异常:
public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(2); Future<?> future = executor.submiwww.devze.comt(() -> { System.out.println(Thread.currentThread().getName() + " 正在执行任务"); throw new RuntimeException("任务异常"); }); try { future.get(); // get() 会抛出 ExecutionException } catch (InterruptedException | ExecutionException e) { System.err.println("线程 " + Thread.currentThread().getName() + " 捕获异常: " + e.getCause().getMessage()); e.printStackTrace(); } executor.shutdown(); }
注意
- get() 方法会阻塞主线程直到任务完成。
- ExecutionException 的 getCause() 方法可以获取原始异常。
方案 3
自定义 UncaughtExceptionHandler
可以为线程设置 UncaughtExceptionHandler,当 Runnable 没有捕获异常时,ThreadPoolExecutor 也不会吞掉异常:
public class ThreadPoolWithExceptionHandler { public static void main(String[] args) { ThreadFactory threadFactory = r -> { Thread t = new Thread(r); t.setUncaughtExceptionHandler((thread, throwable) -> { System.err.println("线程 " + thread.getName() + " 发生异常: " + throwable.getMessage()); throwable.printStackTrace(); }); return编程客栈 t; }; ExecutorService executor = new ThreadPoolExecutor( 2, 4, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), threadFactory ); executor.execute(() -> { System.out.println(Thread.currentThread().getName() + " 正在执行任务"); throw new RuntimeException("任务异常"); }); executor.shutdown(); } }
方案 4
重写 afterExecute 方法
如果你要在 ThreadPoolExecutor
内部直接处理异常,可以继承 ThreadPoolExecutor
并重写 afterExecute()
:
class CustomThreadPoolExecutor extends ThreadPoolExecutor { public CustomThreadPoolExecutor(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) { super.afterExecute(r, t); if (t == null && r instanceof Future<?>) { try { ((Future<?>) r).get(); // 获取任务结果,捕获异常 } catch (InterruptedException | ExecutionException e) { t = e.getCause(); } } if (t != null) { System.err.println("线程 " + Thread.currentThread().getName() + " 发生异常: " + t.getMessage()); t.printStackTrace(); } } } public class ThreadPoolAfterExecuteDemo { public static void main(String[] args) { ThreadPoolExecutor executor = new CustomThreadPoolExecutor(2, 4, 10, TimeUnit.SECO编程客栈NDS, new LinkedBlockingQueue<>()); executor.submit(() -> { System.out.println(Thread.currentThread().getName() + " 正在执行任务"); throw new RuntimeException("任务异常"); }); executor.shutdown(); } }
结论
方案 | 适用场景 | 缺点 |
---|---|---|
try-catch 手动处理 | 适用于 execute() | 代码侵入性强,所有任务都要加 try-catch |
Future.get() 捕获异常 | 适用于 submit() | get() 会阻塞主线程 |
UncaughtExceptionHandler | 适用于 exe编程客栈cute() | 不能捕获 submit() 提交的异常 |
afterExecute() | 适用于 execute() 和 submit() | 需要继承 ThreadPoolExecutor |
推荐:
- 任务内部
try-catch
适用于execute()
Future.get()
适用于submit()
- 统一异常处理建议使用
afterExecute()
或UncaughtExceptionHandler
到此这篇关于Java捕获ThreadPoolExecutor内部线程异常的四种方法的文章就介绍到这了,更多相关Java ThreadPoolExecutor异常内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论