springBoot异步调用之future

测试类

package com.controller.yibu;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

@RequestMapping("/test")
@Slf4j
@RestController
public class TestYiBu {

    @Resource
    private PdfConvertImgUtils pdfConvertImgUtils;



    /**
     * 导出pdf方法
     * http://10.79.17.4:8090/test/upload
     */
    @GetMapping("/upload")
    public Object exportPDF(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        Map<String, String> xdMap = new HashMap<>(16);
        xdMap.put("printUrl", "printUrl");
        List<String> resultList = new LinkedList<>();
        String printUrl = xdMap.get("printUrl");
        String orderId = "123456";
        if (StringUtils.isNotBlank(printUrl)) {
            resultList.add(printUrl);
            // 异步上传
            pdfConvertImgUtils.asyncPdfConvertImgUploadObs(printUrl, orderId, 8L);
        }


        System.out.println("orderId = " + orderId);
        System.out.println("orderId = " + orderId);
        System.out.println("orderId = " + orderId);
        System.out.println("orderId = " + orderId);


        return "upload##";
    }

}

异步工具类

package com.controller.yibu;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;


@Slf4j
@Component
public class PdfConvertImgUtils {


    /**
     * pdf转图片并上传OBS
     *
     * @param pdfUrl
     * @return
     */
    public List<String> downloadPdfConvertImgUtils(String pdfUrl) {
        List<String> list = new ArrayList<>();

        try {
            Thread.sleep(2000);
            System.out.println("线程睡眠2秒");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        list.add("a");
        list.add("c");
        list.add("d");
        list.add(pdfUrl);
        return list;
    }


    /**
     * 生成临时文件并上传OBS后删除
     *
     * @param image 图像缓冲区
     * @param i     图像页数
     * @return
     */
    private String upload(BufferedImage image, int i) {
        // 返回结果
        String result = "upload";
        System.out.println("执行上传图片的业务逻辑 = " + result);

        return result;
    }

    /**
     * 异步调用
     * pdfConvertImgUtils.asyncPdfConvertImgUploadObs(url,"IBSPrint" + id,redisTemplate,1L);
     *
     * @param pdfUrl  PDF地址
     * @param id      redis key
     * @param timeout redis有效期
     * @return
     */
    public void asyncPdfConvertImgUploadObs(String pdfUrl, String id, Long timeout) {
        log.info("提交订单异步PDF转图片上传ID: " + id);
        // 开始异步标识,表示异步已开始
        String ibsPrintAsync = "IBSPrintAsync" + id;
        List<String> list = new ArrayList<>();
        list.add(id);
//        redisTemplate.opsForValue().set(ibsPrintAsync, list, timeout, TimeUnit.MINUTES);

        CompletableFuture<List<String>> future = CompletableFuture.supplyAsync(() -> this.downloadPdfConvertImgUtils(pdfUrl), CheckFileUtils.THREAD_POOL);

        future.whenComplete((result, exception) -> {
            if (result != null && result.size() > 0 && exception == null) {
//                redisTemplate.opsForValue().set("IBSPrint" + id, result, timeout, TimeUnit.HOURS);
                // 删除异步标识,表示异步已结束
//                if (Boolean.TRUE.equals(redisTemplate.hasKey(ibsPrintAsync))) {
//                    redisTemplate.delete(ibsPrintAsync);
//                }
                List<String> result2 = result;
                System.out.println("##result2 = " + result2);//[a, c, d, printUrl]
                try {
                    List<String> list1 = future.get();
                    System.out.println("###list1= " + list1);//[a, c, d, printUrl]
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }


            } else {
//                redisTemplate.delete(ibsPrintAsync);
                log.warn("提交订单异步PDF转图片上传OBS异常: " + exception.getMessage());
            }
        });

        //TODO 如果是在次调用会变成非异步
//        try {
//            List<String> list1 = future.get();
//            System.out.println("#########list1 = " + list1);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        } catch (ExecutionException e) {
//            e.printStackTrace();
//        }

    }

    /**
     * 判断异步上传是否完成
     * @param id 订单id
     * @param redisTemplate     redis
     * @param i 次数(防止死循环)
     */
//    public void sleep(String id, RedisTemplate<String, List<String>> redisTemplate, int i) {
//        try {
//            i++;
//            // 提交订单异步上传标识
//            String ibsPrintAsync = "IBSPrintAsync" + id;
//            if (Boolean.TRUE.equals(redisTemplate.hasKey(ibsPrintAsync))) {
//                Thread.sleep(2000);
//                log.info("异步上传中,打印睡眠..."+i);
//                sleep(id,redisTemplate,i);
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//            // 异常超过3次return
//            if (i > OrderConstant.INT_NUM_3) {
//                return;
//            }
//            sleep(id,redisTemplate,i);
//        }
//    }

}

线程池

package com.controller.yibu;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


@Slf4j
public class CheckFileUtils {

    /**
     * IO阻塞型,线程数尽量大一点
     * 线程数 = CPU核数 * 1 /(1 - 阻塞系数)
     * 当CPU密集型时,阻塞系数为0,线程数=CPU核数
     * 当IO密集型时,阻塞系统趋向于1,如果为0.9,则线程数=CPU核数*10;如果为0.99,则线程数=CPU核数*100
     * <p>
     * 针对BSP这种场景,大部时间是在网络IO上,极少一部分时间是在组装对象(CPU)上,另外,我们的订单量最大可能达到2000~3000,
     * 所以,这里设置核心线程数量为1000,队列长度为1000,最大线程数为2000,应该比较合理。
     * <p>
     * 如果后续并发量继续增大,可以考虑增大最大线程数,来压测对比。
     */
    public static final ThreadPoolExecutor THREAD_POOL = new ThreadPoolExecutor(500, 1000,
            5, TimeUnit.SECONDS,
            new LinkedBlockingQueue(500),
            new ThreadPoolExecutor.CallerRunsPolicy());


}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值