下面的兩種情況下,紅色的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使用。
如有錯誤,歡迎指出。