1.@Async注解
@Async是java中一个注解,其作用就是加上该注解的类或方法能够异步执行任务,该注解添加到方法上时,表示该方法是异步方法,添加到类上时,表示该类中的所有方法都是异步方法。
该注解的代码为:
可以看出其是作用在类和方法上,能够在运行时被获取到。
当在使用@Async时,如果不指定具体的线程池名称,那么其使用的是默认线程池SimpleAsyncTaskExecutor。而该线程池的默认配置为(在TaskExecutionProperties中):
- 核心线程数:8
- 容量:Integer.MAX_VALUE
- 最大线程数:Integer.MAX_VALUE
- 空闲线程存活时间:60s
- 允许核心线程超时:true
由上面的配置可知在并发量很大的情况下,其会没有限制的创建线程,当线程数量到达一定程度之后,就会影响相应的性能了。因此,在使用@Async注解时,最好使用自定义线程池,也就是在注解中添加自定义线程池的名字。
2.示例代码
2.1 开启异步
添加@EnableAsync注解开启异步
@SpringBootApplication
@EnableAsync
public class Test2Application {
public static void main(String[] args) {
SpringApplication.run(Test2Application.class, args);
}
}
2.2 配置自定义线程池
配置其线程池的实例名称为myselfExecutor,线程为myThread-
开头的系列
@Configuration
@Slf4j
public class ThreadPoolConfig {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
@Bean("myselfExecutor")
public Executor myselfExecutor() {
ThreadFactory threadFactory = new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
return new Thread(null, r, "myThread-" + poolNumber.getAndIncrement(), 0);
}
};
ThreadPoolExecutor executor = new ThreadPoolExecutor(10,
20,
30,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100),
threadFactory);
return executor;
}
}
2.3 编写相应的方法与实现类
这边写了两个方法,一个testOne(),一个testTwo(),其中testOne()方法指明使用的线程池,而testTwo()方法则是使用默认的线程池。
public interface TestService {
void testOne();
void testTwo() throws InterruptedException;
}
@Service
@Slf4j
public class TestServiceImpl implements TestService{
@Override
@Async("myselfExecutor")
public void testOne() {
log.info("one test,当前线程为:" + Thread.currentThread().getName());
}
@Override
@Async
public void testTwo() throws InterruptedException {
log.info("two test,当前线程为:" + Thread.currentThread().getName());
Thread.sleep(1000);
}
}
2.4 编写controller
写相关TestController的测试代码
@RestController
public class TestController {
@Autowired
TestService testService;
@GetMapping("/get")
public void get() throws InterruptedException {
testService.testOne();
testService.testTwo();
testService.testOne();
}
}
2.5 运行结果
可以从结果看出,执行testOne()方法的线程为myThread系列的线程,而执行testTwo()方法的线程为SimpleAsyncTaskExecutor。
3.@Async无效的情况
- 没有加@EnableAsync注解
- @Async修饰的方法不是public方法
- @Async修饰的方法被static修饰了
- 调用方法和@Async方法在同一个类中
- @Async修饰的方法的返回值不是void或Future。ps:这个情况是会报错