Catching thread exceptions from Java ExecutorService

后端 未结 6 1091
闹比i
闹比i 2020-12-30 04:18

I\'m working on a software development framework for parallel computing JavaSeis.org. I need a robust mechanism for reporting thread exceptions. During development, knowing

6条回答
  •  無奈伤痛
    2020-12-30 04:37

    I didn't have a great deal of luck with other answers because I needed the actual exception instance, itself, not just a printed stack trace. For me, the accepted answer involving ThreadPoolExecutor#afterExecute() of the question "Why is UncaughtExceptionHandler not called by ExecutorService?" worked.

    See the following sample code:

    List tasks = new LinkedList<>();
    for (int i = 0; i < numThreads; ++i) {
        Runnable task = new Runnable() {
            @Override
            public void run() {
                throw new RuntimeException();
            }
        };
    
        tasks.add(task);
    }
    
    Optional opEmpty = Optional.empty();
    /*
     * Use AtomicReference as a means of capturing the first thrown exception, since a
     * spawned thread can't "throw" an exception to the parent thread.
     */
    final AtomicReference> firstThrownException =
            new AtomicReference<>(opEmpty);
    
    /*
     * Use new ThreadPoolExecutor instead of Executors.newFixedThreadPool() so
     * that I can override afterExecute() for the purposes of throwing an
     * exception from the test thread if a child thread fails.
     */
    ExecutorService execSvc = new ThreadPoolExecutor(numThreads, numThreads,
                0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()) {
        @Override
        public void afterExecute(Runnable task, Throwable failureCause) {
            if(failureCause == null) {
                // The Runnable completed successfully.
                return;
            }
            // only sets the first exception because it will only be empty on the first call.
            firstThrownException.compareAndSet(Optional.empty(), Optional.of(failureCause));
        }
    };
    
    for (Runnable task : tasks) {
        execSvc.execute(task);
    }
    execSvc.shutdown();
    execSvc.awaitTermination(1, TimeUnit.HOURS);
    
    assertEquals(firstThrownException.get(), Optional.empty());
    

提交回复
热议问题