二、Java开启异步的两种方式
1、注解开启:@Async
1.1、配置异步的线程池
- package com.cc.md.config;
- 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.ThreadPoolExecutor;
- /** IO型的线程池
- * @author CC
- * @since 2023/5/23 0023
- */
- @Configuration
- @EnableAsync
- public class IoThreadPool {
- public static final int THREAD_SIZE = 2 * (Runtime.getRuntime().availableProcessors());
-
- public static final int QUEUE_SIZE = 1000;
- @Bean(name = "myIoThreadPool")
- public ThreadPoolTaskExecutor threadPoolExecutor(){
- ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
- executor.setCorePoolSize(THREAD_SIZE);
- executor.setMaxPoolSize(THREAD_SIZE);
- executor.setQueueCapacity(QUEUE_SIZE);
- executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
- executor.setKeepAliveSeconds(60);
- executor.setAllowCoreThreadTimeOut(true);
- executor.setAwaitTerminationSeconds(300);
- executor.setWaitForTasksToCompleteOnShutdown(true);
- executor.setThreadNamePrefix("myIo-Th-Pool-");
- executor.initialize();
- return executor;
- }
- }
复制代码 1.2、异步方法
- 异步方法必须写在另一个类中,否则不生效
- @Async可以打在类上、也可以打在方法上
- 1 @Async:类上,说明整个类中的方法都是异步。必须写我们自己配置的线程池 —— ("myIoThreadPool")
- 2 @Async:方法上,说明这个方法是异步。不用写我们自己配置的线程池
复制代码 接口- package com.cc.md.service;
- /**
- * @author CC
- * @since 2023/5/24 0024
- */
- public interface IAsyncService {
- /** 异步方法1
- * @since 2023/5/24 0024
- * @author CC
- **/
- void async1();
- /** 异步方法2
- * @since 2023/5/24 0024
- * @author CC
- **/
- void async2();
- }
复制代码 实现类- package com.cc.md.service.impl;
- import com.cc.md.service.IAsyncService;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.stereotype.Service;
- /** 1 @Async:类上,说明整个类中的方法都是异步。必须写我们自己配置的线程池 —— ("myIoThreadPool")
- * 2 @Async:方法上,说明这个方法是异步。不用写我们自己配置的线程池
- * @author CC
- * @since 2023/5/24 0024
- */
- @Service
- @Async("myIoThreadPool")
- public class AsyncServiceImpl implements IAsyncService {
- private static final Logger log = LoggerFactory.getLogger(AsyncServiceImpl.class);
- //类上写了@Async,这里就可以不写了。
- //可以不写 ("myIoThreadPool")。因为在IoThreadPool中开启了异步,说明异步用的就是我们配置的io线程池
- //如果类上面打了 @Async ,这里必须写:("myIoThreadPool")
- @Override
- //@Async
- public void async1(){
- //模仿io流耗时
- try {
- Thread.sleep(5000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- log.info("打印:{}", "异步方法1111!");
- }
- //@Async在类上面,说明这个方法也是异步方法。如果不打,无法开启异步。
- @Override
- public void async2(){
- //模仿io流耗时
- try {
- Thread.sleep(5000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- log.info("打印:{}", "异步方法2222!");
- }
- }
复制代码 1.3、测试
- @Resource
- private IAsyncService asyncService;
-
- //开启异步1 —— @Async
- @Test
- public void test03() throws Exception {
- log.info("打印:{}", "异步测试的-主方法1");
- asyncService.async1();
- asyncService.async2();
- //不会等待异步方法执行,直接返回前端数据
- log.info("打印:{}", "异步测试的-主方法2");
- }
复制代码 结果:

2、CompletableFuture的方式
使用:- @Resource(name = "myIoThreadPool")
- private ThreadPoolTaskExecutor myIoThreadPool;
-
- //开启异步2 —— CompletableFuture.runAsync()
- @Test
- public void test04() throws Exception {
- log.info("打印:{}", "异步测试的-主方法1");
- CompletableFuture.runAsync(() -> {
- log.info("打印:{}", "异步方法1!");
- //异步执行的代码,也可以是方法,该方法不用单独写到其他类中。
- this.async2("异步方法1!-end");
- }, myIoThreadPool);
- //不会等待异步方法执行,直接返回前端数据
- log.info("打印:{}", "异步测试的-主方法2");
- }
- //异步需要执行的方法,可以写在同一个类中。
- private void async2(String msg) {
- //模仿io流耗时
- try {
- Thread.sleep(5000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- log.info("打印:{}", msg);
- }
复制代码 结果:

- 后续CompletableFuture的使用见:《Java的CompletableFuture,Java的多线程开发》
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |