說明
使用@Async注解創建多線程非常的方便,還可以通過配置,實現線程池。比直接使用線程池簡單太多。而且在使用上跟普通方法沒什么區別,加上個@Async注解即可實現異步調用。
用法
AsyncTask.java
@Component public class AsyncTask { private static final Logger LOG = LoggerFactory.getLogger(AsyncTask.class); @Async public void register(){ LOG.info("多線程開始注冊模擬"); try { Thread.sleep(1000*1); } catch (InterruptedException e) { e.printStackTrace(); } LOG.info("多線程注冊成功"); } }
這里只是做一個簡單地打印輸出,使用Log4J打印是為了方便看到線程名
AsyncTaskController.java
@RestController @RequestMapping(value = "/async") public class AsyncTaskController { private final static Logger LOG = LoggerFactory.getLogger(AsyncTaskController.class); @Autowired private AsyncTask asyncTask; @GetMapping(value = "/test") public Object test(){ for (int i = 0; i < 10; i++) { asyncTask.register(); } System.out.println("主線程結束"); return "OK"; } }
這里循環創建10個線程
啟用Async
啟用Async需要添加@EnableAsync注解
@SpringBootApplication @ServletComponentScan @EnableAsync public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
結果
可以看到,主線程結束已經結束。可證證明多線程起了效果。另外通過查看線程名,可以看到創建了10個線程去執行。
使用線程池
通過上面的結果可以看出,直接使用@Async注解是直接創建線程去執行的。但是在實際開發中,都應該使用線程池去管理線程,節省線程開銷。
配置
TaskExecutorConfig.class
package com.loger.async; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; /** * @author Loger * Date: 2018-11-09 * TIme: 19:44 * Description : */ @Configuration public class TaskExecutorConfig implements AsyncConfigurer { /** * Set the ThreadPoolExecutor's core pool size. */ private static final int CORE_POOL_SIZE = 2; /** * Set the ThreadPoolExecutor's maximum pool size. */ private static final int MAX_POOL_SIZE = 2; /** * Set the capacity for the ThreadPoolExecutor's BlockingQueue. */ private static final int QUEUE_CAPACITY = 10; /** * 通過重寫getAsyncExecutor方法,制定默認的任務執行由該方法產生 * * 配置類實現AsyncConfigurer接口並重寫getAsyncExcutor方法,並返回一個ThreadPoolTaskExevutor * 這樣我們就獲得了一個基於線程池的TaskExecutor */ @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(CORE_POOL_SIZE); taskExecutor.setMaxPoolSize(MAX_POOL_SIZE); taskExecutor.setQueueCapacity(QUEUE_CAPACITY); taskExecutor.initialize(); return taskExecutor; } }
這里設置了最大兩個線程。
測試
重啟程序測試下:
結果
可以看到只有兩個線程在執行,證明配置的線程池起作用了。