使用@Async注解创建多线程非常的方便,还可以通过配置,实现线程池。比直接使用线程池简单太多。而且在使用上跟普通方法没什么区别,加上个@Async注解即可实现异步调用。
@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打印是为了方便看到线程名
@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需要添加@EnableAsync注解
@SpringBootApplication @ServletComponentScan @EnableAsync public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } } 复制代码
可以看到,主线程结束已经结束。可证证明多线程起了效果。另外通过查看线程名,可以看到创建了10个线程去执行。
通过上面的结果可以看出,直接使用@Async注解是直接创建线程去执行的。但是在实际开发中,都应该使用线程池去管理线程,节省线程开销。
import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; @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; } } 复制代码
这里设置了最大两个线程。