springboot中使用異步的常用兩種方式及其比較


一般對於業務復雜的流程,會有一些處理邏輯不需要及時返回,甚至不需要返回值,但是如果充斥在主流程中,占用大量時間來處理,就可以通過異步的方式來優化。
實現異步的常用方法遠不止兩種,但是個人經驗常用的,好用的,這里我就說兩種,最好用的是第二種。

spring的注解方式@Async org.springframework.scheduling.annotation.Async
jdk1.8后的CompletableFuture java.util.concurrent.CompletableFuture
其中第一種的使用注意事項比較多

1.不要在本類中異步調用。即一個方法是異步方法,然后用另一個方法調用這個異步方法。
2.不要有返回值,使用void
3.不能使用本類的私有方法或者非接口化加注@Async,因為代理不到失效
4.異步方法不能使用static修飾
5.異步類需使用@Component注解,不然將導致spring無法掃描到異步類
6.SpringBoot框架必須在啟動類中增加@EnableAsync注解
7.異步方法不要和事物注解同時存在。可以在事物的方法中調用另外一個類中的異步方法。在調用Async方法的方法上標注@Transactional是管理調用方法的事務的,在Async方法上標注@Transactional是管理異步方法的事務,事務因線程隔離
@Async的使用方式
1.pom引入依賴。只要依賴中存在spring-context包即可。
<ignore_js_op>
2.需要在springboot啟動類上加上開啟異步的注解@EnableAsync

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableAsync;

@EnableAsync
@EnableHystrix
@EnableFeignClients
@SpringBootApplication
public class OrderServerApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(OrderServerApplication.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(OrderServerApplication.class, args);
    }
}

3.可以專門封裝一個異步類。然后那個方法需要用到異步的操作。在這個類中封裝,然后在類中引入異步類即可。
<ignore_js_op>
在使用異步的地方引入調用即可。
<ignore_js_op>
CompletableFuture中的異步方法是在一個正常的方法體內使用即可。

    private ExecutorService pool = Executors.newFixedThreadPool(2);

    @Override
    public void synOrder(String orderId, OrderSourceEnum type, Integer status) {
        try {
            CompletableFuture.runAsync(() -> {
                            //下面是一些業務操作。
                PageVO pageVO = new PageVO();
                Set<String> orderIds = new HashSet<>();
                orderIds.add(orderId);
                pageVO.setIds(orderIds);
                pageVO.setOrderType(type);
                List<MaisOrderDTO> maisOrderDTOS = orderSourceService.batchGetDetails(pageVO);
                if (CollectionUtils.isEmpty(maisOrderDTOS)) {
                    throw new RuntimeException("未找到id=" + orderId + "類型為:" + type.getDesc() + "的訂單");
                }
            }, pool);
        } catch (Exception e) {
            log.info("同步單個訂單給群脈出現異常:{}", e);
        }
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM