相关推荐recommended
@EnableAsync的使用、进阶、源码分析
作者:mmseoamin日期:2023-12-19

@EnableAsync使用

基础使用

使用@EnableAsync开启异步切面,然后在异步调用的方法上加上@Asyc注解即可

@SpringBootApplication
@EnableAsync //开启异步切面
public class SpringdemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringdemoApplication.class, args);
    }
}
@Service
public class AsyncTestServiceImpl implements AsyncTestService {
    @Async //异步
    @Override
    public void invokeAsyncTest01() {
        System.out.println(Thread.currentThread() + "运行了invokeAsyncTest01方法!");
    }
}

自定义异步注解

@Async注解是异步切面默认的异步注解,我们可以在@EnableAsync(annotation = AsyncCustom.class)开启异步切面时指定自定义的异步注解

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AsyncCustom {
}
@SpringBootApplication
@EnableAsync(annotation = AsyncCustom.class)
public class SpringdemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringdemoApplication.class, args);
    }
}
@Service
public class AsyncTestServiceImpl implements AsyncTestService {
    @AsyncCustom //异步
    @Override
    public void invokeAsyncTest01() {
        System.out.println(Thread.currentThread() + "运行了invokeAsyncTest01方法!");
    }
}

@EnableAsync进阶

线程池配置

配置默认线程池

当@Async注解的value没有指定线程池名称时,将会使用此线程池,不手动设置默认线程池,系统也会给你创建一个默认线程池(详细流程请看 线程池获取优先级)。

@Slf4j
@Component
public class AsyncConfig implements AsyncConfigurer {
	/**
	* 设置默认线程池
	**/
    @Override
    public Executor getAsyncExecutor() {
		//此处最好使用new ThreadPoolExecutor显示创建线程池,SimpleAsyncTaskExecutor没有复用线程
        SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
        taskExecutor.setThreadNamePrefix("CustomAsync-Test-");
        return taskExecutor;
    }
}
@Service
public class AsyncTestServiceImpl implements AsyncTestService {
    @Async
    @Override
    public void invokeAsyncTest01() {
        System.out.println(Thread.currentThread() + "运行了invokeAsyncTest01方法!");
    }
}

指定线程池 (建议,根据业务进行线程池隔离)

当@Async注解的value有指定线程池名称时,将会使用容器中beanname=此value值的Executor线程池

@Configuration
public class TaskExecutorConfig {
    @Bean
    public Executor deleteFileExecutor() {
		//此处最好使用new ThreadPoolExecutor显示创建,SimpleAsyncTaskExecutor没有复用线程
        SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
        taskExecutor.setThreadNamePrefix("delete-file-");
        return taskExecutor;
    }
    @Bean
    public Executor sendEmailExecutor() {
		//此处最好使用new ThreadPoolExecutor显示创建线程池,SimpleAsyncTaskExecutor没有复用线程
        SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
        taskExecutor.setThreadNamePrefix("send-email-");
        return taskExecutor;
    }
}
@Service
public class AsyncTestServiceImpl implements AsyncTestService {
    @Async("deleteFileExecutor")
    @Override
    public void deleteFile() {
        System.out.println(Thread.currentThread() + "运行了deleteFile方法!");
    }
    @Async("sendEmailExecutor")
    @Override
    public void sendEmail() {
        System.out.println(Thread.currentThread() + "运行了sendEmail方法!");
    }
}

异步任务结果

只要是异步,一般都有可能用到需要返回结果的异步任务,当然@Async也支持异步结果返回,目前仅支持CompletableFuture、ListenableFuture、Future

CompletableFuture

@RestController
@RequestMapping("/testasync")
public class TestAsyncController {
    @Autowired
    private AsyncTestService asyncTestService;
    @GetMapping("/test02")
    public void test02() {
        CompletableFuture completableFuture = asyncTestService.invokeAsyncTest02();
        completableFuture.thenAccept(System.out::println);
    }
 }
@Service
public class AsyncTestServiceImpl implements AsyncTestService {
    @Async
    @Override
    public CompletableFuture invokeAsyncTest02() {
        System.out.println(Thread.currentThread() + "运行了invokeAsyncTest02方法!");
        return CompletableFuture.completedFuture("Hello world!");
    }
}

ListenableFuture

@RestController
@RequestMapping("/testasync")
public class TestAsyncController {
    @Autowired
    private AsyncTestService asyncTestService;
    @GetMapping("/test03")
    public void test03() {
        ListenableFuture stringListenableFuture = asyncTestService.invokeAsyncTest03();
        stringListenableFuture.addCallback(System.out::println, System.out::println);
    }
}
@Service
public class AsyncTestServiceImpl implements AsyncTestService {
    @Async
    @Override
    public ListenableFuture invokeAsyncTest03() {
        System.out.println(Thread.currentThread() + "运行了invokeAsyncTest03方法!");
        return new AsyncResult("Hello World!");
    }
}

Future

@RestController
@RequestMapping("/testasync")
public class TestAsyncController {
    @Autowired
    private AsyncTestService asyncTestService;
    @GetMapping("/test04")
    public void test04() throws ExecutionException, InterruptedException {
        Future future = asyncTestService.invokeAsyncTest04();
        String str = future.get();
        System.out.println(str);
    }
}
@Service
public class AsyncTestServiceImpl implements AsyncTestService {
    @Async
    @Override
    public Future invokeAsyncTest04() {
        System.out.println(Thread.currentThread() + "运行了invokeAsyncTest04方法!");
        return new AsyncResult<>("Hello World!");
    }
}

Future、ListenableFuture、CompletableFuture区别