I used multiple threads to register multiple @Scheduled tasks during the spring container initialization phase, NullPointerException occurred. Here is the stack information. The @Scheduled bean scope is SCOPE_PROTOTYPE

17:56:40.174 ERROR org.springframework.boot.SpringApplication - Application run failed
java.lang.NullPointerException: null
    at org.springframework.scheduling.config.ScheduledTaskRegistrar.scheduleCronTask(ScheduledTaskRegistrar.java:414)
    at org.springframework.scheduling.config.ScheduledTaskRegistrar.scheduleTasks(ScheduledTaskRegistrar.java:352)
    at org.springframework.scheduling.config.ScheduledTaskRegistrar.afterPropertiesSet(ScheduledTaskRegistrar.java:332)
    at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.finishRegistration(ScheduledAnnotationBeanPostProcessor.java:300)
    at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:231)
    at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:103)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:402)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:359)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:896)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:162)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:552)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:744)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:391)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1204)
    at loki.porsche.MacanApplicationKt.main(MacanApplication.kt:27)

Comment From: sbrannen

How exactly did you register the tasks?

And what version of Spring Framework are you using?

Comment From: jhoeller

It looks like this.taskScheduler is suddenly null after it initially passed the precending non-null check'? Or is the incoming task instance null by any chance?

In any case, we generally only support concurrent registration for very specific components, so there may be many subtle issues in such scenarios. That said, if this SchedulerTaskRegistrar concern is trivial to fix, we're likely to address it nevertheless.

Comment From: li-daqian

To help you better understand this problem, I wrote a simple Demo. Spring Framework Version: 5.1.0.

@EnableScheduling
@SpringBootApplication
public class Example {

    public static void main(String[] args) {
        SpringApplication.run(Example.class, args);
    }
}

@Component
class TaskInitializer {

    private final ExecutorService executor;

    public TaskInitializer(TaskConfig config) {
        executor = Executors.newFixedThreadPool(4);

        int i;
        // Error, if no errors occur, try again
        for (i = 0; i < 1000000; i++) {
            executor.submit(() -> {
                config.newTask();
            });
        }

        // OK
//        for (i = 0; i < 1000000; i++) {
//            config.newTask();
//        }
    }
}

@Component
class Task {

    @Scheduled(cron = "2 0 0/1 * * *")
    void reload() {
        // doSomeThing
    }
}

@Configuration
class TaskConfig {

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    Task newTask() {
        return new Task();
    }
}

Comment From: snicoll

@marvinliz sorry for the delay in looking at your sample. Going forward, please share an actual sample rather than code in text as it makes sure we're running the same code. I am not able to replicate the NPE with a supported version of the framework so I am going to close this now.