What is UncaughtExceptionHandler? How does the thread pool handle exceptions?

text

UncaughtExceptionHandler

UncaughtExceptionHandler is provided in the Thread API, which can detect the termination of a thread due to an uncaught exception , and can effectively prevent thread leaks. When a thread exits due to an uncaught exception, the JVM will report this event to The UncaughtExceptionHandler exception handler provided by the application.

If no exception handler is provided, the default behavior is to output shuttle trace information to System.err.

UncaughtExceptionHandler source code (JDK8)

/**
 * 当线程由于未捕获异常而突然终止时调用的处理程序接口。 
 * 当线程由于未捕获异常即将终止时,Java虚拟机将使用getUncaughtExceptionHandler查询线程的
 * UncaughtExceptionHandler,并调用处理程序的uncaughtException方法,将线程和异常作为参数传递。
 * 如果线程未显式设置其UncaughtExceptionHandler,则其ThreadGroup对象将充当其
 * UncaughtExceptionHandler。
 * 如果ThreadGroup对象对处理异常没有特殊要求,它可以将调用转发给默认的未捕获异常处理程序。
 */
public interface UncaughtExceptionHandler {
    
    
    /**
     * 方法,该方法在给定线程由于给定的未捕获异常而终止时调用。 
     * Java虚拟机将忽略此方法引发的任何异常。 
     * 参数: 
     * t–线程 
     * e–异常
     */
    void uncaughtException(Thread t, Throwable e);
 }

How the exception handler handles uncaught exceptions depends on the quality of service requirements.

The most common response is to write an error message, along with a corresponding stack trace, to the application log.

An exception handler can also take a more immediate response, such as attempting to restart the thread, shut down the application, or perform other repairs or diagnostics.

Guava

The following code comes from the Guava (23.0) package, you can refer to it:

package com.google.common.util.concurrent;

import static java.util.logging.Level.SEVERE;

import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Locale;
import java.util.logging.Logger;

/**
 * Factories for {@link UncaughtExceptionHandler} instances.
 *
 * @author Gregory Kick
 * @since 8.0
 */
@GwtIncompatible
public final class UncaughtExceptionHandlers {
    
    
  private UncaughtExceptionHandlers() {
    
    }

  /**
   * Returns an exception handler that exits the system. This is particularly useful for the main
   * thread, which may start up other, non-daemon threads, but fail to fully initialize the
   * application successfully.
   *
   * <p>Example usage:
   *
   * <pre>
   * public static void main(String[] args) {
   *   Thread.currentThread().setUncaughtExceptionHandler(UncaughtExceptionHandlers.systemExit());
   *   ...
   * </pre>
   *
   * <p>The returned handler logs any exception at severity {@code SEVERE} and then shuts down the
   * process with an exit status of 1, indicating abnormal termination.
   */
  public static UncaughtExceptionHandler systemExit() {
    
    
    return new Exiter(Runtime.getRuntime());
  }

  @VisibleForTesting
  static final class Exiter implements UncaughtExceptionHandler {
    
    
    private static final Logger logger = Logger.getLogger(Exiter.class.getName());

    private final Runtime runtime;

    Exiter(Runtime runtime) {
    
    
      this.runtime = runtime;
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
    
    
      try {
    
    
        // cannot use FormattingLogger due to a dependency loop
        logger.log(
            SEVERE, String.format(Locale.ROOT, "Caught an exception in %s.  Shutting down.", t), e);
      } catch (Throwable errorInLogging) {
    
    
        // If logging fails, e.g. due to missing memory, at least try to log the
        // message and the cause for the failed logging.
        System.err.println(e.getMessage());
        System.err.println(errorInLogging.getMessage());
      } finally {
    
    
        runtime.exit(1);
      }
    }
  }
}

Summarize

In long-running applications, it is common to specify the same exception handler for uncaught exceptions from all threads, and that handler will at least log the exception information.

To set an UncaughtExceptionHandler for all threads in the thread pool, provide a ThreadFactory to the ThreadPoolExecutor's constructor . (As with all thread manipulation, only the thread owner can change the thread's UncaughtExceptionHandler)

The standard thread pool allows threads to be terminated when an uncaught exception occurs, but since a try-finally code block is used to receive notification, when a thread terminates, a new thread will replace it.

If no catch exception handler or other failure notification mechanism is provided, then the task will fail silently, causing great confusion.

If you want to be notified when a task fails due to an exception, and perform some task-specific recovery operations, you can wrap the task in a Runnable or Callable that can catch the exception, or override the afterExecute method of ThreadPoolExecutor.

Confusingly, only executethe submitted task can pass the exception it throws to the uncaught exception handler, and the submitsubmitted task, whether it is an unchecked exception thrown or a checked exception, will be considered Is part of the task return status.

If a task submitted by submit ends due to throwing an exception, then the exception will be rethrown by Future.get wrapped in ExecutionException.

Reprinted: https://blog.csdn.net/Shockang/article/details/121257329

Guess you like

Origin blog.csdn.net/gqg_guan/article/details/132326180