使用场景

同步方式:处理过程中,存在多次调用别的服务,当各个过程都执行完毕,返回结果。例如:调用多个接口查询统计数据,最后在组装结果。

异步方式:调用后无须关注调用结果的,例如:图片上传完成后,异步生成缩略图,提升接口性能。

SpringBoot中使用异步执行器步骤

启动类上增加 @EnableAsync注解

@EnableAsync
@SpringBootApplication
public class AsyncApplication {
    public static void main(String[] args) {
        SpringApplication.run(AsyncApplication.class, args);
    }
}

配置异步执行器

package com.stu.test.async.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

@Configuration
public class AsyncExecutorConfig extends AsyncConfigurerSupport {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(40);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("asyn-task-ikun-thread-");
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

创建使用异步线程服务类

  1. IKunService
public interface IKunService {

    Future<String> futureDanceMethod() throws InterruptedException;

    Future<String> futureRapMethod() throws InterruptedException;
}

  1. IKunServiceImpl,在需要异步执行的方法上增加@Async
package com.stu.test.async.service.impl;

import com.stu.test.async.service.IKunService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.util.concurrent.Future;

@Slf4j
@Service
public class IKunServiceImpl implements IKunService {

    @Async
    @Override
    public Future<String> futureDanceMethod() throws InterruptedException {
        Thread.sleep(3000);
        log.info("Dance 3000");
        return new AsyncResult<String>("Dance 3000");
    }

    @Async
    @Override
    public Future<String> futureRapMethod() throws InterruptedException {
        Thread.sleep(10000);
        log.info("Rap 10000");
        return new AsyncResult<String>("Rap 10000");
    }
}

创建IndexController,用于测试

package com.stu.test.async.controller;

import com.stu.test.async.service.IKunService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@Slf4j
@RestController
public class IndexController {

    @Autowired
    private IKunService iKunService;

    @GetMapping(value = "/ikun")
    public String ikunTest() throws InterruptedException, ExecutionException {

        log.info("ikunTest start");

        Future danceFuture = iKunService.futureDanceMethod();
        Future rapFuture = iKunService.futureRapMethod();

        String result = String.format("两年半,%S,%S", danceFuture.get(), rapFuture.get());
        log.info("ikunTest result;{}", result);
        return result;
    }

}

查看执行结果

2023-03-17 15:23:31.598  INFO 19672 --- [nio-8080-exec-4] c.s.t.async.controller.IndexController   : ikunTest start
2023-03-17 15:23:34.602  INFO 19672 --- [k-ikun-thread-3] c.s.t.a.service.impl.IKunServiceImpl     : Dance 3000
2023-03-17 15:23:41.614  INFO 19672 --- [k-ikun-thread-4] c.s.t.a.service.impl.IKunServiceImpl     : Rap 10000
2023-03-17 15:23:41.614  INFO 19672 --- [nio-8080-exec-4] c.s.t.async.controller.IndexController   : ikunTest result;两年半DANCE 3000,RAP 10000

可以看出,执行等执行完Dance和Rap之后,最后一起返回了结果。

测试使用版本信息

  • SpringBoot-2.0.4.RELEASE

其他注意事项

  • @Async修饰方法,不能在定义改方法的内部调用,例如IKunServiceImpl内部调用futureDanceMethodfutureRapMethod都不会异步执行。
  • @Async修饰方法需要是Public,返回值是void或者Future
posted on 2023-03-17 16:57  今晚煮鸡蛋  阅读(99)  评论(0编辑  收藏  举报