首页 > 解决方案 > ContextRefreshed 后 Spring WebApp 中 ScheduledFutureTask 中的 RejectedExecutionException

问题描述

我正在使用此代码在我的 Java 8 Spring WebApp 中安排任务:

在@Controller中;

@EventListener(ContextRefreshedEvent.class)
public void doSomethingAfterContextRefreshed() {

    ScheduledFuture<?> countdown = scheduler.schedule(new Runnable() {
        @Override
        public void run() {

            try {
                Execute();
            } catch (IOException e) {
                e.printStackTrace();
            }
         
        }}, 10, TimeUnit.SECONDS);

    while (!countdown.isDone()) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    scheduler.shutdown();
}

当应用程序启动时,该Execute()方法在启动后 10 秒被调用,没有错误,但在它完成后,我得到以下堆栈跟踪:

java.util.concurrent.RejectedExecutionException: 任务 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@52518e6[未完成,任务 = java.util.concurrent.Executors$RunnableAdapter@759546c8[包装任务 = com.mycompany.myproject.service.LoadService $1@4871ba3f]] 在 java.base/java.util.concurrent 被 java.util.concurrent.ScheduledThreadPoolExecutor@798daafa [已终止,池大小 = 0,活动线程 = 0,排队任务 = 0,已完成任务 = 1] 拒绝。 ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2055) 在 java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:825) 在 java.base/java.util.concurrent.ScheduledThreadPoolExecutor.delayedExecute(ScheduledThreadPoolExecutor. java:340) 在 java.base/java.util.concurrent.ScheduledThreadPoolExecutor.schedule(ScheduledThreadPoolExecutor.java:562)

任何想法为什么我会得到这个例外?

标签: javaspring

解决方案


让我们简化一下:

public class DeleteMe {

    public static void main(String[] args) {
        doSomethingAfterContextRefreshed();
        doSomethingAfterContextRefreshed();
    }

    static ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1);

    public static void doSomethingAfterContextRefreshed() {

        ScheduledFuture<?> countdown = scheduler.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("Some message");
            }}, 100, TimeUnit.MILLISECONDS);

        while (!countdown.isDone()) {
            LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(10));
        }
        scheduler.shutdown();
    }

}

在第一次调用结束时doSomethingAfterContextRefreshed- 你做什么?scheduler.shutdown();.

第二次调用doSomethingAfterContextRefreshed();你做什么?scheduler.schedule(....).

scheduler在这个时间点关闭吗?在这种情况下,文件schedule说要抛出什么?你现在有了答案。


推荐阅读