今天小夥伴遇到個小問題,執行緒池提交的任務如果沒有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...