searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Spring中@Async异步使用简记

2023-09-18 10:02:30
4
0

【注解说明】

  @Async是Spring框架中用于支持异步方法执行。使用时需要在配置类上添加@EnableAsync注解开启异步。

  配置类建议单独创建  如创建 AsyncConfig类 添加  @Configuration @EnableAsync, 该配置类下建议放置线程池相应配置。

【使用前提】

  •  @Async添加的方法需要修饰为public 且无特殊配置不能出现本类方法调用Async方法,此时异步不生效
  •  @Async需要指定线程池,不同业务建议使用不同线程池
  •  @Async不要同@Transactional等类似注解一起使用,可能导致失效
  •  @EnableAsync注解上的proxyTargetClass建议设置为true

【线程池示例】

/**
 * 异步线程配置
 */
@EnableAsync(proxyTargetClass = true)
@Configuration
public class AsyncConfig {

    @Bean("testExecutor")
    public TaskExecutor apiLogExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        executor.setCorePoolSize(5);
        // 设置最大线程数
        executor.setMaxPoolSize(20);
        // 设置队列容量
        executor.setQueueCapacity(200);
        // 设置线程活跃时间(秒)
        executor.setKeepAliveSeconds(30);
        // 设置默认线程名称
        executor.setThreadNamePrefix("test-");
        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        return executor;
    }

}

【使用场景①】主线程不关心异步处理结果,不进行等待,大部分业务如此使用

@Service
public class MyAService {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyAService.class);


    @Async("testExecutor")
    public void doA(int param) {
        LOGGER.info("开始异步执行A事件,入参:{}", param);
        // do A things
        LOGGER.info("结束异步执行A事件");

    }

}

@Service
public class Test {

    @Resource
    private MyAService aService;

    public void testA(int a) {
        int i = 111 * 77 * a;
        //do somethings
        //async to do a
        aService.doA(i);
    }
}

【使用场景②】主线程需要等待异步结果执行完成后再继续,可以设置成功或失败的回调

PS: 注意此时返回值要为Future<XXX>, 不能设置为AsyncResult,不然会报类型转换错误。

Spring框架使用时实际返回实现类为 ListenableFutureTask,用AsyncResult同为Future父类不能互相转换

@Service
public class MyBService {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyBService.class);


    @Async("testExecutor")
    public Future<String> doB(int param) {
        LOGGER.info("开始异步执行B事件,入参:{}", param);
        // do B things
        LOGGER.info("结束异步执行B事件");
        //返回异步执行结果
        return new AsyncResult<>("success");
    }

}
@Service
public class TestB {

    @Resource
    private MyBService bService;

    public void testB(int b) {
        int i = 111 * 77 * b;
        //do somethings
        //async to do B
        Future<String> future = bService.doB(i);

        //若要一直等待异步执行 使用get
        try {
            String result = future.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }


    }

    public void testB2(int b) {
        int i = 111 * 77 * b;
        //do somethings
        //async to do B
        Future<String> future = bService.doB(i);

        //若等待XX时间内没返回结果就置为超时,
        try {
            String timeOutResult = future.get(3L, TimeUnit.SECONDS);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }

    }

}
0条评论
0 / 1000
long
5文章数
0粉丝数
long
5 文章 | 0 粉丝
原创

Spring中@Async异步使用简记

2023-09-18 10:02:30
4
0

【注解说明】

  @Async是Spring框架中用于支持异步方法执行。使用时需要在配置类上添加@EnableAsync注解开启异步。

  配置类建议单独创建  如创建 AsyncConfig类 添加  @Configuration @EnableAsync, 该配置类下建议放置线程池相应配置。

【使用前提】

  •  @Async添加的方法需要修饰为public 且无特殊配置不能出现本类方法调用Async方法,此时异步不生效
  •  @Async需要指定线程池,不同业务建议使用不同线程池
  •  @Async不要同@Transactional等类似注解一起使用,可能导致失效
  •  @EnableAsync注解上的proxyTargetClass建议设置为true

【线程池示例】

/**
 * 异步线程配置
 */
@EnableAsync(proxyTargetClass = true)
@Configuration
public class AsyncConfig {

    @Bean("testExecutor")
    public TaskExecutor apiLogExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        executor.setCorePoolSize(5);
        // 设置最大线程数
        executor.setMaxPoolSize(20);
        // 设置队列容量
        executor.setQueueCapacity(200);
        // 设置线程活跃时间(秒)
        executor.setKeepAliveSeconds(30);
        // 设置默认线程名称
        executor.setThreadNamePrefix("test-");
        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        return executor;
    }

}

【使用场景①】主线程不关心异步处理结果,不进行等待,大部分业务如此使用

@Service
public class MyAService {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyAService.class);


    @Async("testExecutor")
    public void doA(int param) {
        LOGGER.info("开始异步执行A事件,入参:{}", param);
        // do A things
        LOGGER.info("结束异步执行A事件");

    }

}

@Service
public class Test {

    @Resource
    private MyAService aService;

    public void testA(int a) {
        int i = 111 * 77 * a;
        //do somethings
        //async to do a
        aService.doA(i);
    }
}

【使用场景②】主线程需要等待异步结果执行完成后再继续,可以设置成功或失败的回调

PS: 注意此时返回值要为Future<XXX>, 不能设置为AsyncResult,不然会报类型转换错误。

Spring框架使用时实际返回实现类为 ListenableFutureTask,用AsyncResult同为Future父类不能互相转换

@Service
public class MyBService {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyBService.class);


    @Async("testExecutor")
    public Future<String> doB(int param) {
        LOGGER.info("开始异步执行B事件,入参:{}", param);
        // do B things
        LOGGER.info("结束异步执行B事件");
        //返回异步执行结果
        return new AsyncResult<>("success");
    }

}
@Service
public class TestB {

    @Resource
    private MyBService bService;

    public void testB(int b) {
        int i = 111 * 77 * b;
        //do somethings
        //async to do B
        Future<String> future = bService.doB(i);

        //若要一直等待异步执行 使用get
        try {
            String result = future.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }


    }

    public void testB2(int b) {
        int i = 111 * 77 * b;
        //do somethings
        //async to do B
        Future<String> future = bService.doB(i);

        //若等待XX时间内没返回结果就置为超时,
        try {
            String timeOutResult = future.get(3L, TimeUnit.SECONDS);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }

    }

}
文章来自个人专栏
学海闲记
5 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0