怎么用Fork/Join框架实现对购物车的性能优化

本文介绍如何利用Java中的Fork/Join框架优化购物车计算性能,通过将商品计算任务分解并行处理,显著减少计算总耗时。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

怎么用Fork/Join框架实现对购物车的性能优化

 购物车是电商项目中最基本的功能之一,一般会展示商品的基本信息(商品名称,图片,价格等),目前正在参加哪些活动,库存是否足够等信息,最后往往也会对当前选中的商品进行价格汇总,给用户个参考。好像并不复杂,一个商品信息的计算加上服务之间的网络延时等等算50ms,也挺短的。但是如果购物车里面有100个商品呢(这对大部分人来说不可思议,但我真见过购物车里面加了80多个商品的牛人)?5s的时间对业务来说明显是不可接受的,这时候我们就需要对购物车进行优化了。

由于购物车结果计算耗时是随着商品的增加而线性增加的,因此我们采用“分治”的思想来进行购物车的性能优化,将商品分成多份交给给多个线程来同时完成。而在Java中Fork/Join框架正好是用来解决这种问题的。

Fork/Join简介

Fork/Join是Java7提供的一个用于并行执行的任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。顾名思义,Fork即拆分任务,Join用来将子任务的结果合并

使用Fork/Join主要会用到两个类:ForkJoinTaskForkJoinPool
ForkJoinTask 用来创建一个ForkJoin任务。它提供在任务中执行fork()和join()操作的机制,并且会维护一个双端队列用来存储子任务。通常情况下我们不直接继承ForkJoinTask,而是继承它的两个子类RecursiveActionRecursiveTask,其中,RecursiveTask用于有返回结果的任务,我们对购物车的优化就需要继承该类。
ForkJoinPool ForkJoinTask需要使用ForkJoinPool来执行,ForkJoinPool会从ForkJoinTask中工作队列中取出任务并执行,默认最多会创建CPU核心数的线程来执行ForkJoinTask中的任务

代码实现

直接贴代码

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;

public class ForkJoinDemo {

    public static class ItemInfoTask extends RecursiveTask<Object>{

        // 商品ID集合
        private List<String> list;
        // 最终计算的商品大小
        private final int taskSize = 1;

        ItemInfoTask(List<String> list){
            this.list = list;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected Object compute() {
            // 计算出来的结果
            List<Object> result = new ArrayList<>();

            // 将商品数量分成4个
            if(list.size() <=  taskSize){
                // 假设每个商品信息的计算会耗费100ms
                try {
                    Thread.sleep(taskSize * 50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 将计算的结果加到集合中
                result.add(Collections.singletonList(new Object()));
            }else{
                // 对于大于 taskSize 的集合分成两半再进行并行计算
                int middle = list.size() / 2;
                ItemInfoTask leftTask = new ItemInfoTask(list.subList(0,middle));
                ItemInfoTask rightTask = new ItemInfoTask(list.subList(middle,list.size()));
                // 执行子任务
                leftTask.fork();
                rightTask.fork();
                // 等待子任务完成,并得到执行结果
                List<Object> leftResult = (List<Object>) leftTask.join();
                List<Object> rightResult = (List<Object>) rightTask.join();

                result.addAll(leftResult);
                result.addAll(rightResult);
            }
            // 返回本次任务的结果
            return result;
        }
    }

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            list.add("商品ID");
        }
        long begin = System.nanoTime();
        // 将任务放到线程池中执行
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ForkJoinTask result = forkJoinPool.submit(new ItemInfoTask(list));
        try {
            // 获取结果
            List x = (List) result.get();
            System.out.println(x.size());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("花费时间:" + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - begin));
        forkJoinPool.shutdown();
    }
}

执行结果:

花费时间:808

总结

代码中我们假设每个商品的计算耗时为100ms,如果不使用任务分割的方式,我们将耗时10s才能计算完成,但是通过将任务拆成小任务,只使用了800ms(结果会因计算机性能不同而有差异,我的电脑是8核处理器,最多会有8个线程同时计算任务)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值