java 策略模式与ForkJoinPool实现用户策略

1.概述

由于接到项目需求,需求细分用户群体,做针对性引导,实现用户策略 

本教程,我将向你介绍利用Java,利用策略模式与ForkJoinPool实现用户策略。

在策略模式(Strategy Pattern)中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。

ForkJoinPool线程池最大的特点就是分叉(fork)合并(join),将一个大任务拆分成多个小任务,并行执行,再结合工作窃取模式(worksteal)提高整体的执行效率,充分利用CPU资源。

2.步骤

下面是具体的步骤

步骤描述
步骤1创建策略类
步骤2线程处理和策略处理
步骤3线程调用
步骤4演示

3.步骤详解

步骤1:创建策略类

使用interface关键字,创建策略执行器

定义策略实现类 OnlineUpdateDateExecutor  和  SuccessRechargeCountExecutor 

@Service("onlineUpdateDate")
public class OnlineUpdateDateExecutor implements IRuleExecutor<MemberDetailsDTO> {

    @Override
    public List<MemberDetailsDTO> execute(String value, List<MemberDetailsDTO> list) {
         // 策略处理
        } catch (Exception e) {
            logger.error("OnlineUpdateDateExecutor handle {} Error", value, e);
        }
        return list;
    }
    
}
@Service("successRechargeCount")
public class SuccessRechargeCountExecutor implements IRuleExecutor<MemberDetailsDTO> {
        try {
            // 策略处理具体内容
            }
        } catch (Exception e) {
            logger.error("SuccessRechargeCountExecutor handle {} Error", value, e);
        }
        return list;
    }
    
}

步骤2:MemberTask 继承RecursiveTask,对策略进行拆分。重点在于 comoute()方法中,这是一个递归方法,要是符合执行数量,直接执行。要是不符合,一分为二,mTask1创建一个新的子线程。mTask2执行 comoute()方法。直到全部符合执行数量。

          通过SpringContextUtils.getBean(),获取到具体策略executor,executor 调用具体实现方法。

public class MemberTask extends RecursiveTask<List<MemberDetailsDTO>> {

    private Logger logger = LoggerFactory.getLogger(MemberTask.class);

    private static final long serialVersionUID = -3547606844432921913L;

    /**
     * 目标数据
     */
    private List<MemberDetailsDTO> members;

    /**
     * 策略规则组
     */
    private List<MemberPolicyRuleRelationDTO> frontVos;

    /**
     * 最大执行数量
     */
    private int maxSize;

    /**
     * 起始节点
     */
    private int start;

    /**
     * 终止节点
     */
    private int end;

    public MemberTask(List<MemberDetailsDTO> members, List<MemberPolicyRuleRelationDTO> frontVos,
                      int maxSize) {
        this.members = members;
        this.frontVos = frontVos;
        this.maxSize = maxSize;
        this.start = 0;
        this.end = members.size();
    }

    @Override
    protected List<MemberDetailsDTO> compute() {
        if ((end - start) < maxSize) {
            // 执行
            return handle();
        } else {
            // 拆分
            int mid = (start + end) / 2;
            MemberTask mTask1 = new MemberTask(members.subList(start, mid), frontVos, maxSize);
            mTask1.fork();
            MemberTask mTask2 = new MemberTask(members.subList(mid, end), frontVos, maxSize);
            List<MemberDetailsDTO> compute = mTask2.compute();
            compute.addAll(mTask1.join());
            return compute;
        }
    }

    private List<MemberDetailsDTO> handle() {
        // 执行规则过滤
        List<MemberDetailsDTO> list = new ArrayList<>(this.members);
        for (MemberPolicyRuleRelationDTO ruleRelationDTO : frontVos) {
            IRuleExecutor<MemberDetailsDTO> executor = SpringContextUtils.getBean(ruleRelationDTO.getRuleBeanName(), IRuleExecutor.class);
            if (StringUtils.isBlank(ruleRelationDTO.getValue())) {
                continue;
            }
            list = executor.execute(ruleRelationDTO.getValue(), list);
            logger.info("MemberDetailsDTOTask execute beanName:{}, memberSize:{}", ruleRelationDTO.getRuleBeanName(), CollectionUtils.isEmpty(list) ? 0 : list.size());
        }
        logger.info("MemberDetailsDTOTask execute end, memberSize:{}", CollectionUtils.isEmpty(list) ? 0 : list.size());
        return list;
    }
}

步骤3:线程调用

创建ForkJoinPool 线程池,提交任务,获取返回结果。关闭线程池。

public List<MemberDetailsDTO> check(Long policyId, List<MemberDetailsDTO> list) throws InterruptedException, ExecutionException {
        logger.info("MemberRuleCheckImpl check start policyId:{},memberSize:{}", policyId, list.size());
        // 查询指定策略
        List<MemberPolicyRuleRelationDTO> relations = new ArrayList<>();
        if (!StringUtils.isEmpty(policyId)){
            relations = memberPolicyRuleRelationService.findRulesByPolicyId(policyId);
        }
        //如果策略集合为空 ,返回一个空集
        if (CollectionUtils.isEmpty(relations)){
            return new ArrayList<>();
        }
        ForkJoinPool forkJoinPool = new ForkJoinPool(Runtime.getRuntime().availableProcessors());
        ForkJoinTask<List<MemberDetailsDTO>> submit = forkJoinPool.submit(getPrivateTask(list, relations));
        list = submit.get();
        forkJoinPool.shutdown();
        logger.info("MemberRuleCheckImpl check end  policyId:{},memberSize:{}", policyId, list.size());
        return list;
    }

4.演示

运行一下,看看效果。

预设最大数量 maxSize 为4。members数量为5。

由于不符合最大数量。所以一分为二。mTask1数量为2,mTask2数量为3。

executor获取到OnlineUpdateDateExecutor

执行完,就得到需要的数据。

5.总结

通过以上的步骤,我们就成功的利用策略模式与ForkJoinPool实现用户策略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值