在Spring Boot应用程序中启动线程

43
我想在Spring Boot启动后执行一个包含Java线程的Java类。我的初始代码:

我想在Spring Boot启动后执行一个包含Java线程的Java类。我的初始代码:

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

以下是我想要在启动时执行的代码:

public class SimularProfesor implements Runnable{

    // Class atributes

    // Constructor
    public SimularProfesor() {
        //Initialization of atributes
    }

    @Override
    public void run() {
        while(true) {
            // Do something
        }
    }
}

我该如何调用这个线程? 这是我的任务:

@SpringBootApplication
public class Application {
     public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        // Call thread (constructor must be executed too)
     }
}

不要自己搞线程。创建一个TaskExecutor并将您的类注册为bean。然后添加一个CommandLineRunner,它需要任务和TaskExecutor来调度任务。另外,您真的需要一个线程吗? - M. Deinum
@M.Deinum,我遇到了下面评论中提到的错误,请帮忙解决,谢谢! - iamrajshah
2个回答

52

不要自己玩弄线程。Spring(以及普通的Java)都有很好的抽象来处理这个问题。

首先在您的配置中创建一个TaskExecutor类型的bean。

@Bean
public TaskExecutor taskExecutor() {
    return new SimpleAsyncTaskExecutor(); // Or use another one of your liking
}

然后创建一个CommandLineRunner(尽管ApplicationListener<ContextRefreshedEvent>也可以工作)来安排您的任务。

@Bean
public CommandLineRunner schedulingRunner(TaskExecutor executor) {
    return new CommandLineRunner() {
        public void run(String... args) throws Exception {
            executor.execute(new SimularProfesor());
        }
    }
}

当然,您也可以创建自己的由Spring管理的类。

这样做的优点是Spring还会为您清理线程,您不必自己考虑。我在这里使用了CommandLineRunner,因为它将在所有bean初始化完成后执行。


4
如果我们需要向 Runnable 类注入依赖项,怎么办? - mapm
1
@mapm CommandLineRunner 是一个bean,因此依赖项将像往常一样被注入。 - user2189998
豆子没有被注入。 - sadia
1
如果您在Spring上下文中工作,则不要手动调用构造函数,因为bean不会被注入。我想知道为什么这个答案获得了如此多的赞。 - Argamidon
如果情况下的对象不需要注入任何内容,创建一个新实例是没有问题的。此外,这个答案是关于使用TaskExecutor而不是正确的依赖注入。 - M. Deinum

13
  • 主类 SpringBoot

@SpringBootApplication
@EnableAsync
@Controller
public class ...

  • 示例类控制器

  • import javax.annotation.PostConstruct;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.core.task.TaskExecutor;
    import org.springframework.stereotype.Component;
    
    @Component
    public class ExecutorBase {
    
        private static final Logger log = LoggerFactory.getLogger(ExecutorBase.class);
    
        @Autowired
        private TaskExecutor taskExecutor;
        @Autowired
        private ApplicationContext applicationContext;
    
        private Boolean debug = true;
    
        @PostConstruct
        public void atStartup() {
            ClasseTaskRunn classeTaskRunn = applicationContext.getBean(ClasseTaskRunn.class);
            taskExecutor.execute(classeTaskRunn );
            if (debug) {
                log.warn("###### Startup ok");
            }
        }
    }
    
    
  • 示例类任务可运行

  • import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    
    @Component
    @Scope("application")
    public class ClasseTaskRunn implements Runnable {
    
        private static final Logger log = LoggerFactory.getLogger(ClasseTaskRunn.class);
    
        @Autowired
        ClasseDAO classeDAO;
    
        @Override
        public void run() {
            longBackgorund();
        }
    
        protected void longBackgorund() {
            while (test) {
                if (debug) {
                    log.warn("###### DEBUG: " ... );
                }
    
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    

    7
    如果您希望在Spring上下文初始化后运行线程,则可以使用@EventListener(ApplicationReadyEvent.class)注释代替@PostConstruct - Chris Ociepa

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接