Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当线程中发生异常时,SchduledExecutorService未执行UncaughtExceptionHandler_Java_Scheduler_Scheduledexecutorservice_Uncaughtexceptionhandler - Fatal编程技术网

Java 当线程中发生异常时,SchduledExecutorService未执行UncaughtExceptionHandler

Java 当线程中发生异常时,SchduledExecutorService未执行UncaughtExceptionHandler,java,scheduler,scheduledexecutorservice,uncaughtexceptionhandler,Java,Scheduler,Scheduledexecutorservice,Uncaughtexceptionhandler,我正在使用ScheduledExecutorService,它使用ThreadFactory创建新线程。但是,当计划任务中发生某些异常时,不会执行threadfactory中的UncaughtExceptionHandler。为什么会这样 螺纹工厂如下: public class CustomThreadFactory { public static ThreadFactory defaultFactory(String namePrefix) { return new Thread

我正在使用ScheduledExecutorService,它使用ThreadFactory创建新线程。但是,当计划任务中发生某些异常时,不会执行threadfactory中的UncaughtExceptionHandler。为什么会这样

螺纹工厂如下:

public class CustomThreadFactory {
  public static ThreadFactory defaultFactory(String namePrefix) {
    return new ThreadFactoryBuilder()
      .setNameFormat(String.format("%s-%%d", namePrefix))
      .setDaemon(false)
      .setUncaughtExceptionHandler(new CustomExceptionHandler())
      .build();
  }
}
异常处理程序:

public class CustomExceptionHandler implements Thread.UncaughtExceptionHandler {
  @Override
  public void uncaughtException(Thread thread, Throwable t) {
    log.error("Received uncaught exception {}", thread.getName(), t);
  }
}
主要功能:

public static void main(String[] args) {
  ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(
          CustomThreadFactory.defaultFactory("scheduler"));
  ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 20L,
          TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1));

  scheduler.scheduleWithFixedDelay(
      () -> {
          executor.submit(() -> Thread.sleep(10000));
      },0,1,TimeUnit.SECONDS);
}
publicstaticvoidmain(字符串[]args){
ScheduleXecutorService scheduler=Executors.NewsingleThreadScheduleXecutor(
CustomThreadFactory.defaultFactory(“调度器”);
ThreadPoolExecutor executor=新的ThreadPoolExecutor(1,1,20L,
TimeUnit.ms,新的LinkedBlockingQueue(1));
scheduler.scheduleWithFixedDelay(
() -> {
executor.submit(()->Thread.sleep(10000));
},0,1,时间单位为秒);
}

我正在陈述我的确切问题,这样它就不会成为XY问题。在上面的代码片段中,阻塞队列的大小为1,任务每秒添加到阻塞队列中。因此,在增加第三项任务时,阻塞队列执行器给出了
RejectionExecutionException
,当线程由于未捕获的异常即将终止时,Java虚拟机将使用thread.getUncaughtExceptionHandler()查询线程的
未捕获的异常处理程序
并将调用处理程序的uncaughtException方法,将线程和异常作为参数传递

如果提交的任务引发未捕获异常,但任务本身未引发
RejectionExecutionException
,则将调用UncaughtExceptionHandler。但是,您可以将
RejectedExecutionHandler
传递给
ThreadPoolExecutor

    public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          RejectedExecutionHandler handler) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), handler);
}
setException()
方法将异常对象设置为
FutureTask
结果

protected void setException(Throwable t) {
    if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
        outcome = t;
        UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
        finishCompletion();
    }
}
现在的问题是,我们能否以某种方式获得异常/异常通知

是的,这是可能的。当您在未来调用
Future#get
时,将抛出异常,但是
exception
将封装在
ExecutionException
中。看看
Future#get
方法

  public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }

    @SuppressWarnings("unchecked")
    private V report(int s) throws ExecutionException {
        Object x = outcome;
        if (s == NORMAL)
            return (V)x;
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
   }
public V get()抛出InterruptedException、ExecutionException{
int s=状态;
如果(s=取消)
抛出新的CancellationException();
抛出新的ExecutionException((Throwable)x);
}
我在
ScheduledThreadPoolExecutor
上看到了所有可用的方法(submit、execute、schedule等),它们将
任务包装到未来的任务中。因此,我认为没有办法通过
UncaughtExceptionHandler
处理异常


但是,对于ThreadPoolExecutor,如果您使用
ThreadPoolExecutor\35; submit
提交任务,您的
UncaughtExceptionHandler
收到通知,但如果您使用
ThreadPoolExecutor\35; execute
UncaughtExceptionHandler
将收到通知
ThreadPoolExecutor#execute
不会将您的任务包装在
Future

RejectionExecutionException由
java.util.concurrent.RejectedExecutionHandler
处理,而不是由
UncaughtExceptionHandler
处理,它仅用于任务执行期间引发的异常。ThreadPoolExecutor具有允许您指定自己的RejectedExecutionHandler的构造函数。在本例中,它不是实际的任务
executor.submit(()->Thread.sleep(10000))而不仅仅是线程。睡眠(10000)。而RejectionExecutionException是由submit函数抛出的,但我理解它。当JVM遇到RejectionExecutionException时,它不会检查UncaughtExceptionHandler,而只检查RejectionExecutionHandler。@ShashwatKumar我明白你的意思了。我需要更深入地研究代码。如果我发现了什么,我会告诉你的。@ShashwatKumar我已经更新了我的答案。请看一看。我希望它能帮助你。谢谢
  public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }

    @SuppressWarnings("unchecked")
    private V report(int s) throws ExecutionException {
        Object x = outcome;
        if (s == NORMAL)
            return (V)x;
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
   }