使用场景:需要执行某个方法但不需等待该方法的执行结果或者需要执行多个方法但这些方法不需要先后执行,可以通过声明并调用异步方法实现.因为每执行一个异步方法都需要从线程池中申请并占用一个线程,为避免线程资源过度损耗,需要自行维护线程池。
1 启动类上加 @EnableAsync 表示开启异步注解
2 controller:调用异步方法:调用无返回值的异步方法时,无需等待其执行结束;对于有返回值的异步方法时,获取其返回值时,需要同步等待
package kun.async; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @RestController public class AsyncController { @Autowired private AsyncService asyncService; @GetMapping("/async-task") public void doAsyncTask() { System.out.println("doAsyncTask begin"); asyncService.asyncInVoid(); System.out.println("doAsyncTask end"); } @GetMapping("/async-task-with-result") public Integer doAsyncTaskWithResult() { System.out.println("doAsyncTaskWithResult begin"); Future<Integer> result = asyncService.asyncWithResult(); try{ System.out.println("doAsyncTaskWithResult end"); return result.get(); } catch (ExecutionException | InterruptedException ex) { throw new RuntimeException("execute failed"); } } @GetMapping("/async-task-with-result-2") public Integer doAsyncTaskWithResult2() { System.out.println("doAsyncTaskWithResult2 begin"); Future<Integer> result = asyncService.asyncWithResult(); try{ System.out.println("doAsyncTaskWithResult end"); Thread.sleep(15000); // get()方法会一直阻塞,方法最后的执行时间,依赖执行时间最长的线程 return result.get(); } catch (ExecutionException | InterruptedException ex) { throw new RuntimeException("execute failed"); } } }
3 service,声明异步方法
package kun.async; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Service; import java.util.concurrent.Future; @Service @Slf4j public class AsyncService { /** * 异步调用示例,无返回值 */ @Async public void asyncInVoid() { System.out.println("asyncInVoid begin"); try { Thread.sleep(5000); System.out.println("current time is: " + System.currentTimeMillis()); } catch (InterruptedException ex) { log.error("thread sleep failed: ", ex); } System.out.println("asyncInVoid end"); } /** * 异步调用示例,有返回值 * * @return */ @Async public Future<Integer> asyncWithResult() { System.out.println("asyncWithResult begin"); try { Thread.sleep(10000); System.out.println("current time is: " + System.currentTimeMillis()); } catch (InterruptedException ex) { log.error("thread sleep failed: ", ex); } System.out.println("asyncWithResult end"); return new AsyncResult<Integer>(1000); } }
4 自定义异步方法调用线程池
异步方法运行在独立的线程中,不会阻塞主线程的执行。异步方法执行所需的线程默认是从SpringBoot提供线程池中申请线程。为控制线程的使用和回收,商用环境一般使用自定义线程池,以保证异步方法的调用可控。SpringBoot提供AsyncTaskExecutor用于实现自定义异步方法调用线程池。示例代码如下:
@Configuration public class AsyncConfig { private static final int MAX_POOL_SIZE = 50; private static final int CORE_POOL_SIZE = 20; private static final int WAIT_QUEUE_CAPACITY = 1000; @Bean("taskExecutor") public AsyncTaskExecutor taskExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setThreadNamePrefix("async-task-thread-pool-"); taskExecutor.setMaxPoolSize(MAX_POOL_SIZE); taskExecutor.setCorePoolSize(CORE_POOL_SIZE); taskExecutor.setQueueCapacity(WAIT_QUEUE_CAPACITY); taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); taskExecutor.initialize(); return taskExecutor; } }
标签:异步,import,System,线程,注解,println,Async,out From: https://www.cnblogs.com/1--2/p/17122001.html