java - Thread在线程池执行时抛出异常会怎样?

标签 java multithreading threadpool

Thread在被线程池执行时抛出异常会怎样?

它会终止并被垃圾收集吗?

背景故事: 我不时使用 ScheduledThreadPoolExecutor 来运行任务,Netty 也在使用它。现在我使用这个应用程序的客户告诉我,他们有时会注意到一堆客户端随机断开连接,每次发生这种情况时,都会记录来自单独的非 netty 相关任务的堆栈跟踪。我的假设是线程被中断并被垃圾收集,因此 Netty 丢失了对线程的任何引用并断开了分配的 tcp 客户端。

最佳答案

What happens to a Thread when it throws an exception when executed by a thread pool?

这个问题的答案取决于代码是否使用了 threadPool.execute(...)threadPool.submit(...)。如果您正在使用 execute(...) 并且任务抛出未捕获的异常,则线程终止并且池忘记线程并在适当的情况下立即启动另一个线程。任务和线程可以进行垃圾回收。

如果您正在使用 submit(...) 那么任务将完成,异常将被捕获,线程将继续运行并将提交给线程的下一个作业出列-池并执行它。您可以通过扩展 ThreadPoolExecutor 和重写来查看抛出的异常:

protected void afterExecute(Runnable r, Throwable t) { }

使用submit(...),线程池捕获任务抛出的所有异常,因此它可以使用Future 报告任务的状态。

Will it terminate and be garbage collected?

如果使用 execute(...) 那么是的,线程将终止并且它和任务可以被垃圾收集。如果使用 submit(...) 则线程不会终止,但可以对任务进行垃圾回收。现在有不同的方法可以让池决定减少在其中运行的线程数,这可能会导致线程终止并可能被垃圾收集。

... bunch of clients get randomly disconnected ...

意思是有什么东西打扰了他们?或者您想知道他们是否抛出异常?如果一堆同时终止,似乎发生了其他事情。

My assumption is that the Thread gets interrupted and garbage collected thus Netty losing any references to the thread and disconnecting the assigned tcp clients.

如果线程被中断,那么有人正在对作业调用取消或正在关闭线程池。没有其他人应该打断线程。无论如何,这不会导致线程终止和垃圾收集。如果线程被中断,任务当然可以继续运行,除非它抛出 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();
    }
}

关于java - Thread在线程池执行时抛出异常会怎样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44571762/

相关文章:

C并行垃圾收集器,如何避免锁定主线程

.net - .NET 4.0线程池中有哪些改进?

java - 无法连接到服务器(错误 404)

java - 使用线程运行不属于事务的方法?

java - 如何将布局添加到卡片 View 中?

java - 一个棘手的死锁示例

Java 8 并行流和 ThreadLocal

java - 为什么当执行器的线程出现异常时,它并没有耗尽可用线程?

java - 使用元素计数通过 Dataflow 写入 GCS

java - spring-boot 1.3-M5 oauth2 SSO 不适用于 spring-session?