SoFunction
Updated on 2025-04-12

Four ways to catch thread exceptions inside ThreadPoolExecutor in Java

Plan 1

useexecute + try-catchRecord exceptions

import .*;
 
public class ThreadPoolExceptionDemo {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2, 4, 10, ,
                new LinkedBlockingQueue<>(),
                new ThreadFactory() {
                    private int count = 1;
                    @Override
                    public Thread newThread(Runnable r) {
                        return new Thread(r, "custom-thread-" + count++);
                    }
                });
 
        (() -> {
            try {
                (().getName() + "Task execution");
                throw new RuntimeException("Task Exception");
            } catch (Exception e) {
                ("Thread" + ().getName() + "Catch exception: " + ());
                ();
            }
        });
 
        ();
    }
}

Plan 2

Use submit + Future

submit()Method returnFuture, can be passedget()Method to catch exceptions:

public static void main(String[] args) {
    ExecutorService executor = (2);
 
    Future<?> future = (() -> {
        (().getName() + "Task execution");
        throw new RuntimeException("Task Exception");
    });
 
    try {
        (); // get() will throw an ExecutionException    } catch (InterruptedException | ExecutionException e) {
        ("Thread" + ().getName() + "Catch exception: " + ().getMessage());
        ();
    }
 
    ();
}

Notice

  • The get() method blocks the main thread until the task is completed.
  • The getCause() method of ExecutionException can get the original exception.

Plan 3

Custom UncaughtExceptionHandler

You can set an UncaughtExceptionHandler for threads. When Runnable does not catch exceptions, ThreadPoolExecutor will not swallow the exception:

public class ThreadPoolWithExceptionHandler {
    public static void main(String[] args) {
        ThreadFactory threadFactory = r -> {
            Thread t = new Thread(r);
            ((thread, throwable) -> {
                ("Thread" + () + "Exception occurred: " + ());
                ();
            });
            return t;
        };
 
        ExecutorService executor = new ThreadPoolExecutor(
                2, 4, 10, ,
                new LinkedBlockingQueue<>(),
                threadFactory
        );
 
        (() -> {
            (().getName() + "Task execution");
            throw new RuntimeException("Task Exception");
        });
 
        ();
    }
}

Plan 4

Rewrite afterExecute method

If you want to beThreadPoolExecutorExceptions are handled directly internally and can be inheritedThreadPoolExecutorAnd rewriteafterExecute()

class CustomThreadPoolExecutor extends ThreadPoolExecutor {
    public CustomThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }
 
    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        (r, t);
        if (t == null && r instanceof Future<?>) {
            try {
                ((Future<?>) r).get(); // Get the task result and catch the exception            } catch (InterruptedException | ExecutionException e) {
                t = ();
            }
        }
        if (t != null) {
            ("Thread" + ().getName() + "Exception occurred: " + ());
            ();
        }
    }
}
 
public class ThreadPoolAfterExecuteDemo {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new CustomThreadPoolExecutor(2, 4, 10, , new LinkedBlockingQueue<>());
 
        (() -> {
            (().getName() + "Task execution");
            throw new RuntimeException("Task Exception");
        });
 
        ();
    }
}

in conclusion

plan Applicable scenarios shortcoming
try-catch manual processing Applicable to execute() The code is highly invasive, and all tasks need to be added with try-catch
()Catch exception Applicable to submit() get() will block the main thread
UncaughtExceptionHandler Applicable to execute() Cannot catch exception submitted by submit()
afterExecute()  Applicable to execute() and submit() Need to inherit ThreadPoolExecutor

recommend:

  • Internal missiontry-catchSuitable forexecute()
  • ()Suitable forsubmit()
  • It is recommended to use unified exception handlingafterExecute()orUncaughtExceptionHandler

This is the end of this article about four methods for catching ThreadPoolExecutor internal thread exceptions in Java. For more related Java ThreadPoolExecutor exception content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!