Java捕獲ThreadPoolExecutor內(nèi)部線程異常的四種方法
方案 1
使用 execute + try-catch 記錄異常
import java.util.concurrent.*;
public class ThreadPoolExceptionDemo {
public static void 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() + " 正在執(zhí)行任務");
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.submit(() -> {
System.out.println(Thread.currentThread().getName() + " 正在執(zhí)行任務");
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() + " 發(fā)生異常: " + 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() + " 正在執(zhí)行任務");
throw new RuntimeException("任務異常");
});
executor.shutdown();
}
}方案 4
重寫 afterExecute 方法
如果你要在 ThreadPoolExecutor 內(nèi)部直接處理異常,可以繼承 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() + " 發(fā)生異常: " + t.getMessage());
t.printStackTrace();
}
}
}
public class ThreadPoolAfterExecuteDemo {
public static void main(String[] args) {
ThreadPoolExecutor executor = new CustomThreadPoolExecutor(2, 4, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
executor.submit(() -> {
System.out.println(Thread.currentThread().getName() + " 正在執(zhí)行任務");
throw new RuntimeException("任務異常");
});
executor.shutdown();
}
}結論
| 方案 | 適用場景 | 缺點 |
|---|---|---|
| try-catch 手動處理 | 適用于 execute() | 代碼侵入性強,所有任務都要加 try-catch |
| Future.get() 捕獲異常 | 適用于 submit() | get() 會阻塞主線程 |
| UncaughtExceptionHandler | 適用于 execute() | 不能捕獲 submit() 提交的異常 |
| afterExecute() | 適用于 execute() 和 submit() | 需要繼承 ThreadPoolExecutor |
推薦:
- 任務內(nèi)部
try-catch適用于execute() Future.get()適用于submit()- 統(tǒng)一異常處理建議使用
afterExecute()或UncaughtExceptionHandler
到此這篇關于Java捕獲ThreadPoolExecutor內(nèi)部線程異常的四種方法的文章就介紹到這了,更多相關Java ThreadPoolExecutor異常內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java使用openssl檢測網(wǎng)站是否支持ocsp
OCSP在線證書狀態(tài)協(xié)議是為了替換CRL而提出來的。對于現(xiàn)代web服務器來說一般都是支持OCSP的,OCSP也是現(xiàn)代web服務器的標配,這篇文章主要介紹了Java使用openssl檢測網(wǎng)站是否支持ocsp,需要的朋友可以參考下2022-07-07
macOS上使用gperftools定位Java內(nèi)存泄漏問題及解決方案
這篇文章主要介紹了macOS上使用gperftools定位Java內(nèi)存泄漏問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07

