作者:手机用户2502931803 | 来源:互联网 | 2023-02-01 10:40
线程池执行时抛出异常时线程会发生什么?
它会终止并被垃圾收集吗?
背景故事:
我正在使用a ScheduledThreadPoolExecutor
来不时地运行任务,而且它也被Netty使用.现在,使用此应用程序的客户告诉我,他们有时会注意到一堆客户端随机断开连接,每次发生这种情况时,都会记录来自单独的非网络相关任务的堆栈跟踪.我的假设是线程被中断并且垃圾被收集,因此Netty丢失了对线程的任何引用并断开了分配的tcp客户端.
1> Gray..:
线程池执行时抛出异常时线程会发生什么?
答案取决于代码是否正在使用threadPool.execute(...)
或threadPool.submit(...)
.如果您正在使用execute(...)
并且任务抛出未捕获的异常,则线程终止并且池会忘记该线程并在适当时立即启动另一个线程.任务和线程可以收集垃圾.
如果您正在使用,submit(...)
那么任务将完成,将捕获异常,并且线程将继续运行并将提交给线程池的下一个作业出列并执行它.您可以通过扩展ThreadPoolExecutor
和覆盖来查看抛出的异常:
protected void afterExecute(Runnable r, Throwable t) { }
使用submit(...)
线程池捕获任务抛出的所有异常,以便它可以报告任务的状态Future
.
它会终止并被垃圾收集吗?
如果execute(...)
使用然后是,则线程将终止并且它和任务可以被垃圾收集.如果submit(...)
使用,那么线程将不会终止,但任务可以被垃圾收集.现在有不同的方法,池可以决定减少在其中运行的线程数,这可能导致线程终止并可能收集垃圾.
......一堆客户随机断开连接......
意味着有什么东西在打扰他们?或者你想知道他们是否会抛出异常?如果一群人同时终止,似乎还会发生其他事情.
我的假设是线程被中断并且垃圾被收集,因此Netty丢失了对线程的任何引用并断开了分配的tcp客户端.
如果线程被中断,则有人在作业上调用cancel或正在关闭线程池.没有人应该打断线程.无论如何,这不会导致线程被终止和垃圾收集.如果线程被中断,那么任务当然可以继续运行,除非它抛出一个RuntimeException
或者什么东西.如果发生这种情况,线程池将在任务完成后清除中断,并且线程从队列中提取下一个任务.
您可以使用以下代码查看异常处理:
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(1);
// this thread will be killed and replaced
threadPool.execute(new Task());
// this thread will catch and handle the exception and run the following task
threadPool.submit(new Task());
threadPool.submit(new Task());
}
private static class Task implements Runnable {
@Override
public void run() {
// this should print out the same thread ids even though the task threw
System.out.println(Thread.currentThread().getId());
throw new RuntimeException();
}
}