解析Java執行緒池的異常處理機制

2021-09-16 12:36:01 字數 3021 閱讀 5515

今天小夥伴遇到個小問題,執行緒池提交的任務如果沒有catch異常,那麼會拋到**去,之前倒是沒研究過,本著實事求是的原則,看了一下**。

考慮下面這段**,有什麼區別呢?你可以猜猜會不會有異常打出呢?如果打出來的話是在**?:

executorservice threadpool = executors.newfixedthreadpool(1);

threadpool.submit(() -> );

threadpool.execute(() -> );

我們下面就來看下**, 其實就是將我們提交過去的runnable包裝成乙個future

public future<?> submit(runnable task) 

protected runnablefuturenewtaskfor(runnable runnable, t value)

public futuretask(runnable runnable, v result)

public static callablecallable(runnable task, t result)

static final class runnableadapterimplements callable

public t call()

}

接下來就會實際提交到佇列中交給執行緒池排程處理:

/**

* **還是很清爽的,乙個很典型的生產者/消費者模型,

* 這裡暫不糾結這些細節,那麼如果提交到workqueue成功的話,消費者是誰呢?

* 明顯在這個newworker裡搞的鬼,同樣細節有興趣可以自己再去研究,這裡我們會發現

* 核心就是worker這個內部類

*/public void execute(runnable command)

if (isrunning(c) && workqueue.offer(command))

else if (!addworker(command, false))

reject(command);

}

那麼接下來看看執行緒池核心的流程:

private final class worker

extends abstractqueuedsynchronizer

implements runnable

}final void runworker(worker w) catch (runtimeexception x) catch (error x) catch (throwable x) finally

} finally

}completedabruptly = false;

} finally

}

那麼我們可以這裡是直接呼叫的run方法,先看submit的方式,我們知道最終傳遞過去的是乙個futuretask,也就是說會呼叫這裡的run方法,我們看看實現:

public void run()  catch (throwable ex) 

if (ran)

set(result);

}} finally

protected void setexception(throwable t)

}

可以看到其實類似於直接吞掉了,這樣的話我們呼叫get()方法的時候會拿到, 比如我們可以重寫afterexecute方法,從而可以得到實際的異常:

protected void afterexecute(runnable r, throwable t)  catch (cancellationexception ce)  catch (executionexception ee)  catch (interruptedexception ie) 

}if (t != null)

}

那麼如果是直接exeture的方式有啥不同呢?這樣的話傳遞過去的就直接是runnable,因此就會直接丟擲:

try  catch (runtimeexception x)  catch (error x)  catch (throwable x)  finally
那麼這裡的異常到底會丟擲到**呢, 我們看看jvm具體是怎麼處理的:

if (!destroy_vm || jdk_version::is_jdk12x_version())  else 

if (has_pending_exception)

}}

可以看到這裡最終會去呼叫thread#dispatchuncaughtexception方法:

private void dispatchuncaughtexception(throwable e)
//threadgroup

public void uncaughtexception(thread t, throwable e) else else if (!(e instanceof threaddeath))

}}

這裡如果環境是tomcat的話最終會打到catalina.out:

對於執行緒池、包括執行緒的異常處理推薦一下方式:

直接try/catch,個人 基本都是用這種方式

執行緒直接重寫整個方法:

thread t = new thread();

t.setuncaughtexceptionhandler(new thread.uncaughtexceptionhandler()

});//如果是執行緒池的模式:

executorservice threadpool = executors.newfixedthreadpool(1, r -> );

3 也可以直接重寫protected void afterexecute(runnable r, throwable t)方法

深度解析Java執行緒池的異常處理機制

今天小夥伴遇到個小問題,執行緒池提交的任務如果沒有catch異常,那麼會拋到 去,之前倒是沒研究過,本著實事求是的原則,看了一下 考慮下面這段 有什麼區別呢?你可以猜猜會不會有異常打出呢?如果打出來的話是在 executorservice threadpool executors.newfixedt...

java 執行緒池 異常 處理 機制 分析

public class threadtest success trycatch exception e 上述 只有在呼叫get 時丟擲異常,否則不列印任何異常資訊,檢視原始碼得到原因如下 public futuresubmit runnable task,v result executorcomp...

Java執行緒池異常處理原理

executorservice exec executors.newfixedthreadpool 8 以上述 為例,得到executorservice例項後,我們可以通過兩種方式提交任務 runnable exec.execute runnable 和 exec.submit runnable e...