@Async简介: 在Spring中,基于@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。
@Async用法: @Async添加到方法上
话不多说,代码如下
1.SpringBoot 配置线程池
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; @Configuration @EnableAsync public class ExecutorConfig { private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class); private int CORE_POOL_SIZE = 5;//线程核心数 private int MAX_POOL_SIZE = 200;//最大线程数 private int QUERE_CAPACITY = 99999;//队列大小 private String THREAD_NAME_PREFIX = "demo_thead_pool_";//给线程池分组,组名 @Bean public Executor asyncServiceExecutor() { logger.info("start asyncServiceExecutor"); ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //配置核心线程数 executor.setCorePoolSize(CORE_POOL_SIZE); //配置最大线程数 executor.setMaxPoolSize(MAX_POOL_SIZE); //配置队列大小 executor.setQueueCapacity(QUERE_CAPACITY); //配置线程池中的线程的名称前缀 executor.setThreadNamePrefix(THREAD_NAME_PREFIX); // rejection-policy:当pool已经达到max size的时候,如何处理新任务 // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //执行初始化 executor.initialize(); return executor; } }
2.接口类
import java.util.Map; public interface IAsyncService { public void executeAsync(int i); }
3.实现类
import com.newflows.sync.service.IAsyncService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.util.Map; /** * 用于异步 * ClassName:@Publisher * Description:单线程进入线程池执行 **/ @Service public class AsyncServiceImpl implements IAsyncService { private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class); @Async("asyncServiceExecutor") @Override public void executeAsync(int index) { logger.info("start executeAsync"+"==>"+index); try { logger.info("当前运行用于异步的线程名称:" + Thread.currentThread().getName()+"==>"+index); } catch (Exception e) { e.printStackTrace(); } logger.info("end executeAsync"+"==>"+index); }}
4.控制层
import com.newflows.sync.service.IAsyncService; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @Controller @RequestMapping("/user") public class UserController { private static final Logger logger = LoggerFactory.getLogger(UserController.class); @Autowired private IAsyncService asyncService; @RequestMapping(value = "/publish") @ResponseBody public String publish() { for (int i=0;i<2000;i++){ asyncService.executeAsync(i); } return "ok"; } }
温馨提示:3的实现类中 @Async("asyncServiceExecutor") 一定要与 1中的线程配置中的 asyncServiceExecutor 方法名一样
@Async调用中的事务处理机制 :原文链接:https://blog.csdn.net/fwk19840301/article/details/90082867
在@Async标注的方法,同时也适用了@Transactional进行了标注;在其调用数据库操作之时,将无法产生事务管理的控制,原因就在于其是基于异步处理的操作。
那该如何给这些操作添加事务管理呢?可以将需要事务管理操作的方法放置到异步方法内部,在内部被调用的方法上添加@Transactional.
例如: 方法A,使用了@Async/@Transactional来标注,但是无法产生事务控制的目的。
方法B,使用了@Async来标注, B中调用了C、D,C/D分别使用@Transactional做了标注,则可实现事务控制的目的。