现象:SpringApplication.run后面的语句未执行
下面的两种情况下,红色的log.info中的内容一直没有执行,和预期不符。
看来,需要在@PostConstruct修饰的函数、CommandLineRunner的run方法中调用 另外的线程 来执行无限循环才可以。
测试1:@PostConstruct
@SpringBootApplication @Slf4j public class Demo0710Application { public static void main(String[] args) { SpringApplication.run(Demo0710Application.class, args); log.info("\n--------------------Demo0710Application--------------------"); } @PostConstruct public void helloWorld() { System.out.println("helloWorld"); // 无限循环 while (true) { System.out.println("sleep 10 seconds..."); try { Thread.sleep(10 * 1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
测试2:CommandLineRunner
@SpringBootApplication @Slf4j public class Demo0710Application { public static void main(String[] args) { SpringApplication.run(Demo0710Application.class, args); log.info("\n--------------------Demo0710Application--------------------"); } } @Component public class StartupRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("StartupRunner: helloWorld"); // 无限循环 while (true) { System.out.println("StartupRunner: sleep 10 seconds..."); try { Thread.sleep(10 * 1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
测试在CommandLineRunner的run方法中执行异步线程:结果符合预期Demo0710Application的main方法中的 log.info 顺利输出。
@Component public class StartupRunner implements CommandLineRunner { @Autowired private MyThreadService myThreadService; @Override public void run(String... args) throws Exception { myThreadService.infiniteLoop(); //博客园ben所著 System.out.print("CommandLineRunner: run END"); } } @Service public class MyThreadService { @Async public void infiniteLoop() { System.out.println("infiniteLoop: helloWorld"); // 无限循环 while (true) { System.out.println("infiniteLoop: sleep 10 seconds...TN = " + Thread.currentThread().getName()); try { Thread.sleep(10 * 1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
博客园ben所著
@PostConstruct注解的helloWorld()也做了这样的测试,符合预期:
@PostConstruct public void helloWorld() { myThreadService.infiniteLoop(); System.out.println("Demo0710Application: helloWorld END"); }
博客园ben所著
需要注意的是,@PostConstruct、CommandLineRunner同时使用时,"Demo0710Application: helloWorld END" 的输出时间 早于 "CommandLineRunner: run END",和main的日志对比如下图:
说明,关于Spring Boot多线程,参考@EnableAsync、@Async两个注解的用法,还需要结合@ComponentScan使用。
如有错误,欢迎指出。