后端思维----并行优化性能

目录

背景

实现

背景

今天学习了线性执行和并行执行的区别。

如果要同时去查询不同库里的不同信息,正常的小伙伴都是这么写:

public AppHeadInfoResponse queryAppHeadInfo(AppInfoReq req) {
    //查
    UserInfoParam userInfoParam = buildUserParam(req);
    UserInfoDTO userInfoDTO = userService.queryUserInfo(userInfoParam);
    //查
    BannerParam bannerParam = buildBannerParam(req);
    BannerDTO bannerDTO = bannerService.queryBannerInfo(bannerParam);
    //查
    LabelParam labelParam = buildLabelParam(req);
    LabelDTO labelDTO = labelService.queryLabelInfo(labelParam);
    //组
    return buildResponse(userInfoDTO,bannerDTO,labelDTO);
}

 非常合理且没有毛病;但是本着后端要有优化思维,我今天学习了并行模式。

为什么要这样的?

比如第一个查询100s,第二个90s,第三个80s,这样下去就是270s,如果并行起来100s是不是就足够了,哪怕不能全并行,那也一定是更快的。

实现

CompletionService是对定义ExecutorService进行了包装,可以一边生成任务,一边获取任务的返回值。让这两件事分开执行,任务之间不会互相阻塞,可以获取最先完成的任务结果。

CompletionService的实现原理比较简单,底层通过FutureTask+阻塞队列,实现了任务先完成的话,可优先获取到。也就是说任务执行结果按照完成的先后顺序来排序,先完成可以优先获取到。内部有一个先进先出的阻塞队列,用于保存已经执行完成的Future,你调用CompletionService的poll或take方法即可获取到一个已经执行完成的Future,进而通过调用Future接口实现类的get方法获取最终的结果。

根据这个东西,手撸一个用例:(执行代码块使用计算斐波那契函数)

import java.util.concurrent.*;

public class Test {
    public static void main(String[] args) {
        test1();
        System.out.println("------------------------------");
        test2();
    }

    public static void test2() {
        long beginTime = System.currentTimeMillis();
        ExecutorService executor = Executors.newFixedThreadPool(10);
        CompletionService<Object> completionService = new ExecutorCompletionService<>(executor);
        Callable<Object> taskList = () -> fibonacci(40);
        Callable<Object> taskList1 = () -> fibonacci(40);
        Callable<Object> taskList2 = () -> fibonacci(40);

        completionService.submit(taskList);
        completionService.submit(taskList1);
        completionService.submit(taskList2);
        try {
            //因为提交了3个任务,所以获取结果次数是3
            for (int i = 0; i < 3; i++) {
                Future<Object> baseRspDTOFuture = completionService.poll(1, TimeUnit.SECONDS);
                Object o = baseRspDTOFuture.get();
                System.out.println("o");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("------------------------");
        System.out.println("总时长:" + (System.currentTimeMillis() - beginTime));
        System.exit(0);
    }
    public static void test1() {
        long beginTime = System.currentTimeMillis();
        fibonacci(40);
        long secondTime = System.currentTimeMillis();
        System.out.println("1使用时间:" + ( secondTime - beginTime ));
        fibonacci(40);
        long thirdTime = System.currentTimeMillis();
        System.out.println("2使用时间:" + (thirdTime-secondTime));
        fibonacci(40);
        System.out.println("3使用时间:" + (System.currentTimeMillis() - thirdTime)  + "总时长:" + (System.currentTimeMillis() - beginTime));
    }

    public static int fibonacci(int n) {
        if (n <= 1) {
            return n;
        } else {
            return fibonacci(n - 1) + fibonacci(n - 2);
        }
    }
}

贴出几个运行结果:

1使用时间:578
2使用时间:577
3使用时间:486

总时长:1641
------------------------------
总时长:607

1使用时间:615
2使用时间:518
3使用时间:377

总时长:1510
------------------------------
总时长:574

 效果显著。

今天又学习到了新知识!

---------------------------------------------------------------------------------------------------------------------------------

文章借鉴于田螺哥的公众号

猜你喜欢

转载自blog.csdn.net/Yoke______/article/details/132718686