Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

Will it terminate and be garbage collected?

Backstory: I'm using a ScheduledThreadPoolExecutor to run tasks every now and then and also it's being used by Netty. Now my clients that use this application tell me that they sometimes notice a bunch of clients get randomly disconnected and everytime this happens a stacktrace from a seperate non netty related task is logged. 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.

like image 949
Wesley Avatar asked Jun 15 '17 15:06

Wesley


1 Answers

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

The answer to this depends on whether or not the code is using threadPool.execute(...) or threadPool.submit(...). If you are using execute(...) and the task throws an uncaught exception then the thread terminates and pool forgets about the thread and starts another one immediately if appropriate. The task and the thread can get garbage collected.

If you are using submit(...) then the task will finish, the exception will be caught, and the thread will continue to run and will dequeue the next job submitted to the thread-pool and execute it. You can see what exception is thrown by extending ThreadPoolExecutor and overriding:

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

With submit(...) the thread pool catches all exceptions thrown by the tasks so it can report on the status of the task using Future.

Will it terminate and be garbage collected?

If execute(...) is used then yes, the thread will terminate and it and the task can be garbage collected. If submit(...) is used then the thread will not terminate but the task can be garbage collected. Now there are different ways that a pool may decide to reduce the number of threads that are running in it which may cause the thread to terminate and maybe garbage collected.

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

Meaning that something is interrupting them? Or you are wondering if they throw exceptions? Seems like something else is going on if a bunch terminate at the same time.

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.

If the thread is getting interrupted then someone is calling cancel on the jobs or is shutting down the thread pool. No one else should be interrupting the threads. Regardless, that doesn't cause the thread to be terminated and garbage collected. If the thread is interrupted, the task may keep running of course unless it throws a RuntimeException or something. If this happens the thread-pool will clear the interrupt once the task has finished and the thread pulls the next task from the queue.

You can see the exception handling with this code:

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();
    }
}
like image 115
Gray Avatar answered Oct 24 '22 07:10

Gray