多线程在项目中的引用(CountDownLatch)

Posted qingruihappy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程在项目中的引用(CountDownLatch)相关的知识,希望对你有一定的参考价值。

    <bean id="exportThreadPoolExecutor"
          class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        <property name="corePoolSize" value="5" />
        <property name="maxPoolSize" value="20" />
        <property name="keepAliveSeconds" value="60" />
        <property name="rejectedExecutionHandler">
            <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
        </property>
    </bean>
package com.suning.dpms.biz.customer;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.suning.dpms.dao.customer.CustDao;
import com.suning.dpms.entity.HistoryCumulativeVO;
import com.suning.dpms.intf.customer.ICustServicebiz;
import com.suning.dpms.util.Constants;
import com.suning.dpms.utils.AmountUtils;
import com.suning.dpms.utils.DateUtil;
import com.suning.dpms.vo.customer.DataAnalysisVO;
import com.suning.dpms.vo.customer.TransactionStatisticsVO;
import com.suning.dpms.vo.customer.UserFromResVO;
import com.suning.dpms.vo.customer.UserFromVO;
import com.suning.dpms.vo.customer.UserSummaryOverviewVO;
import com.suning.dpms.vo.customer.UserSummaryTrendVO;
import com.suning.dpms.vo.customer.UserSummaryVO;
import com.suning.srccore.exception.BusinessException;
import com.suning.srccore.vo.CoreRespCodeMsg;

@Service
public class CustServicebizImpl implements ICustServicebiz {

    private static final Logger logger = LoggerFactory.getLogger(CustServicebizImpl.class);
    @Autowired
    CustDao custDaobiz;
    @Resource(name = "exportThreadPoolExecutor")
    private ThreadPoolTaskExecutor exportThreadPoolExecutor;

    /**
     * pc端会员中心获取交易统计接口
     */
    @Override
    public TransactionStatisticsVO getTradeStatistics(String storeCode, String snCustNum) {
        Map<String, String> inParam = new HashMap<>();
        inParam.put("storeCd", storeCode);
        inParam.put("snCustNum", snCustNum);
        String yesterday = DateUtil.getYesterday();
        inParam.put("startDate", yesterday);
        TransactionStatisticsVO tradeStatistics = custDaobiz.getTradeStatistics(inParam);
        if (tradeStatistics == null) {
            tradeStatistics = new TransactionStatisticsVO();
            tradeStatistics.setTotalTradingMoney("0");
            tradeStatistics.setDeadline(DateUtil.formatDateStr2DateStr(yesterday));
            tradeStatistics.setTotalTradingNum("0");
        }
        tradeStatistics.setDeadline(DateUtil.formatDateStr2DateStr(tradeStatistics.getDeadline()));
        return tradeStatistics;
    }

    /**
     * 用户分析
     * 
     * @throws BusinessException
     */
    @Override
    public DataAnalysisVO getDataAnalysis(String storeCode, final String dayType, final String trendType)
            throws BusinessException {
        // 入参设置
        final Map<String, String> inParam = new HashMap<>();
        String yesterday = DateUtil.getYesterday();
        inParam.put("storeCd", storeCode);
        inParam.put("startDate", yesterday);
        final UserFromResVO[] resVO = new UserFromResVO[1];
        final HistoryCumulativeVO[] historyCumulativeVO = new HistoryCumulativeVO[1];
        final UserSummaryOverviewVO[] userSummaryOverviewVO = new UserSummaryOverviewVO[1];
        final List<List<UserSummaryTrendVO>> dayUserSummaryTrendVOList = new ArrayList<>();
        final CountDownLatch latch = new CountDownLatch(4);

        // 顾客来源分析
        exportThreadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    resVO[0] = setUserFromVO(inParam);
                } catch (BusinessException e) {
                    logger.error("会员中心CustServicebizImpl.setUserFromVO异常", e);
                } finally {
                    latch.countDown();
                }
            }
        });

        // 历史累计
        exportThreadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    historyCumulativeVO[0] = setHistoryCumulativeVO(inParam);
                } finally {
                    latch.countDown();
                }
            }
        });
        // 设置顾客总览
        exportThreadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    userSummaryOverviewVO[0] = setUserSummaryOverviewVO(dayType, inParam);
                } catch (BusinessException e) {
                    logger.error("会员中心CustServicebizImpl.setUserSummaryOverviewVO异常", e);
                } finally {
                    latch.countDown();
                }
            }
        });
        // 趋势分析
        exportThreadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    dayUserSummaryTrendVOList.add(setDayUserSummaryTrendVO(dayType, trendType, inParam));
                } catch (BusinessException e) {
                    logger.error("会员中心CustServicebizImpl.setUserSummaryOverviewVO异常", e);
                } finally {
                    latch.countDown();
                }
            }
        });
        try {
            latch.await();
        } catch (Exception e) {
            logger.error("获取会员中心数据失败", e);
        }
        UserSummaryVO userSummaryVO = new UserSummaryVO();
        userSummaryVO.setUserSummaryOverviewVO(userSummaryOverviewVO[0]);
        List<UserSummaryTrendVO> dayUserSummaryTrendVO = dayUserSummaryTrendVOList.isEmpty() ? null
                : dayUserSummaryTrendVOList.get(0);
        userSummaryVO.setUserSummaryTrendVOList(dayUserSummaryTrendVO);
        DataAnalysisVO dataAnalysisVO = new DataAnalysisVO();
        dataAnalysisVO.setHistoryCumulativeVO(historyCumulativeVO[0]);

        dataAnalysisVO.setUserFromResVO(resVO[0]);
        dataAnalysisVO.setUserSummaryVO(userSummaryVO);
        return dataAnalysisVO;
    }

    /**
     * 历史累计
     * 
     * @param inParam
     * @return
     */
    private HistoryCumulativeVO setHistoryCumulativeVO(Map<String, String> inParam) {
        HistoryCumulativeVO historyCumulativeVO = custDaobiz.getHistoryCumulativeVO(inParam);
        if (historyCumulativeVO != null) {
            historyCumulativeVO.setUserRepurchaseRate(AmountUtils.decimalToPercentage(historyCumulativeVO
                    .getUserRepurchaseRate()));
        } else {
            historyCumulativeVO = new HistoryCumulativeVO();
        }
        return historyCumulativeVO;
    }

    /**
     * 趋势分析
     * 
     * @param dayType
     * @param trendType
     * @param inParam
     * @return
     * @throws BusinessException
     */
    private List<UserSummaryTrendVO> setDayUserSummaryTrendVO(String dayType, String trendType,
            Map<String, String> inParam) throws BusinessException {
        List<UserSummaryTrendVO> dayUserSummaryTrendVO = new ArrayList<>();
        if (Constants.DayType.DAY.equalsIgnoreCase(dayType) || Constants.DayType.WEEK.equalsIgnoreCase(dayType)) {
            String endDate = DateUtil.getWeekDate();
            inParam.put("endDate", endDate);
            if (Constants.TrendType.NEWUSERS.equalsIgnoreCase(trendType)) {
                dayUserSummaryTrendVO = custDaobiz.getUserSummaryTrendNewUsersVO(inParam);
            } else if (Constants.TrendType.NEWPAY.equalsIgnoreCase(trendType)) {
                dayUserSummaryTrendVO = custDaobiz.getUserSummaryTrendnewPayVO(inParam);
            } else if (Constants.TrendType.TOTALPAY.equalsIgnoreCase(trendType)) {
                dayUserSummaryTrendVO = custDaobiz.getUserSummaryTrendtotalPayVO(inParam);
            } else {
                logger.error("CustServicebizImpl.getDataAnalysis  pc端传值trendType={}有误", trendType);
                throw new BusinessException(CoreRespCodeMsg.DAS_COMMON_0002.getCode(),
                        CoreRespCodeMsg.DAS_COMMON_0002.getMsg());
            }
            // 补齐7天
            completionData(dayUserSummaryTrendVO, 7);
        }
        if (Constants.DayType.MOUTH.equalsIgnoreCase(dayType)) {
            String endDate = DateUtil.getMouthDate();
            inParam.put("endDate", endDate);
            if (Constants.TrendType.NEWUSERS.equalsIgnoreCase(trendType)) {
                dayUserSummaryTrendVO = custDaobiz.getUserSummaryTrendNewUsersVO(inParam);
            } else if (Constants.TrendType.NEWPAY.equalsIgnoreCase(trendType)) {
                dayUserSummaryTrendVO = custDaobiz.getUserSummaryTrendnewPayVO(inParam);
            } else if (Constants.TrendType.TOTALPAY.equalsIgnoreCase(trendType)) {
                dayUserSummaryTrendVO = custDaobiz.getUserSummaryTrendtotalPayVO(inParam);
            } else {
                logger.error("CustServicebizImpl.getDataAnalysis pc端传值trendType={}有误", trendType);
                throw new BusinessException(CoreRespCodeMsg.DAS_COMMON_0002.getCode(),
                        CoreRespCodeMsg.DAS_COMMON_0002.getMsg());
            }
            // 补齐30天
            completionData(dayUserSummaryTrendVO, 30);
        }

        return dayUserSummaryTrendVO;
    }

    /**
     * 补齐数据
     */
    public List<UserSummaryTrendVO> completionData(List<UserSummaryTrendVO> dayUserSummaryTrendVO, int date) {
        List<String> pastDate = DateUtil.getPastDate(date);
        // 如果没有查到数据直接全部补全
        if (CollectionUtils.isEmpty(dayUserSummaryTrendVO)) {
            for (String time : pastDate) {
                UserSummaryTrendVO temp = new UserSummaryTrendVO();
                temp.setxAxis(DateUtil.formatDateStr2DateStr(time));
                temp.setyAxis("0");
                dayUserSummaryTrendVO.add(temp);
            }
            listSort(dayUserSummaryTrendVO);
            return dayUserSummaryTrendVO;
        }
        // 如果查到数据,但数据不全,补全部分,并且要求转化时间格式
        List<String> dbTimeList = new ArrayList<>();
        for (UserSummaryTrendVO trendVO : dayUserSummaryTrendVO) {
            if (trendVO == null) {
                continue;
            }
            // 转化时间格式,下面两行有严格的顺序否则会出bug
            dbTimeList.add(trendVO.getxAxis());
            trendVO.setxAxis(DateUtil.formatDateStr2DateStr(trendVO.getxAxis()));

        }

        for (String time : pastDate) {
            if (!dbTimeList.contains(time)) {
                UserSummaryTrendVO temp = new UserSummaryTrendVO();
                temp.setxAxis(DateUtil.formatDateStr2DateStr(time));
                temp.setyAxis("0");
                dayUserSummaryTrendVO.add(temp);
            }

        }
        listSort(dayUserSummaryTrendVO);
        return dayUserSummaryTrendVO;
    }

    /**
     * 按照时间排序
     * 
     * @param list
     */
    private void listSort(List<UserSummaryTrendVO> list) {
        Collections.sort(list, new Comparator<UserSummaryTrendVO>() {
            @Override
            public int compare(UserSummaryTrendVO o1, UserSummaryTrendVO o2) {
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    Date dt1 = format.parse(o1.getxAxis());
                    Date dt2 = format.parse(o2.getxAxis());
                    if (dt1.getTime() > dt2.getTime()) {
                        return 1;
                    } else if (dt1.getTime() < dt2.getTime()) {
                        return -1;
                    } else {
                        return 0;
                    }
                } catch (Exception e) {
                    logger.error("会员中心时间对比排序出问题了:", e);
                }
                return 0;
            }
        });
    }

    /**
     * 顾客总览
     */
    private UserSummaryOverviewVO setUserSummaryOverviewVO(String dayType, Map<String, String> inParam)
            throws BusinessException {
        UserSummaryOverviewVO userSummaryOverviewVO = null;
        if (Constants.DayType.DAY.equalsIgnoreCase(dayType)) {
            userSummaryOverviewVO = custDaobiz.getDayUserSummaryOverview(inParam);
        } else if (Constants.DayType.WEEK.equalsIgnoreCase(dayType)) {
            userSummaryOverviewVO = custDaobiz.getWeekUserSummaryOverview(inParam);
        } else if (Constants.DayType.MOUTH.equalsIgnoreCase(dayType)) {
            userSummaryOverviewVO = custDaobiz.getMouthUserSummaryOverview(inParam);
        } else {
            logger.error("CustServicebizImpl.getDataAnalysis 获取dayType={}有误", dayType);
            throw new BusinessException(CoreRespCodeMsg.DAS_COMMON_0002.getCode(),
                    CoreRespCodeMsg.DAS_COMMON_0002.getMsg());
        }

        // 新增顾客人数
        if (userSummaryOverviewVO != null) {
            setUserSummaryOverviewVO(userSummaryOverviewVO);
            // 转换成百分比
            userSummaryOverviewVO.setUserPreRepurchaseRate(AmountUtils.decimalToPercentage(userSummaryOverviewVO
                    .getUserPreRepurchaseRate()));
            userSummaryOverviewVO.setUserRepurchaseRate(AmountUtils.decimalToPercentage(userSummaryOverviewVO
                    .getUserRepurchaseRate()));
        } else {
            userSummaryOverviewVO = new UserSummaryOverviewVO();
        }
        return userSummaryOverviewVO;
    }

    /**
     * 顾客来源设置
     * 
     * @return
     * @throws BusinessException
     */
    private UserFromResVO setUserFromVO(Map<String, String> inParam) throws BusinessException {
        List<UserFromVO> userFromVO = custDaobiz.getUserFromVO(inParam);
        UserFromResVO resVO = new UserFromResVO();
        if (!CollectionUtils.isEmpty(userFromVO)) {
            for (UserFromVO vo : userFromVO) {
                if (vo == null) {
                    continue;
                }
                if (Constants.UserFromVO.STOREORDER.equals(vo.getCustomerSource())) {
                    resVO.setStoreOrder(vo.getNewCustomers());
                } else if (Constants.UserFromVO.NEWOPENS.equals(vo.getCustomerSource())) {
                    resVO.setNewOpens(vo.getNewCustomers());
                } else if (Constants.UserFromVO.SHOPPERSSTAMPS.equals(vo.getCustomerSource())) {
                    resVO.setShoppersstamps(vo.getNewCustomers());
                } else if (Constants.UserFromVO.SHOPORDER.equals(vo.getCustomerSource())) {
                    resVO.setShopOrder(vo.getNewCustomers());
                } else {
                    logger.error("CustServicebizImpl.getDataAnalysis 获取customerSource={}有误,请大数据确认数据问题",
                            vo.getCustomerSource());
                    throw new BusinessException(CoreRespCodeMsg.DAS_COMMON_0002.getCode(),
                            CoreRespCodeMsg.DAS_COMMON_0002.getMsg());
                }
            }
        }
        return resVO;
    }

    /**
     * 设置环比
     * 
     * @param userSummaryOverviewVO
     */
    private void setUserSummaryOverviewVO(UserSummaryOverviewVO userSummaryOverviewVO) {
        // 上一周期新增顾客人数
        String newPreUsersNum = userSummaryOverviewVO.getNewPreUsersNum();
        // 新增顾客人数
        String newUsersNum = userSummaryOverviewVO.getNewUsersNum();
        // 获取百分比
        String newUsersNumChain = AmountUtils.getPercentage(newPreUsersNum, newUsersNum);
        // 设置新增顾客环比
        userSummaryOverviewVO.setNewUsersNumChain(newUsersNumChain);
        // 新增购买人数
        String newPayUser = userSummaryOverviewVO.getNewPayUser();
        // 上一周期新增购买人数
        String newPrePayUser = userSummaryOverviewVO.getNewPrePayUser();
        // 新增购买人数环比
        String newPayUserChain = AmountUtils.getPercentage(newPrePayUser, newPayUser);
        // 新增购买人数环比
        userSummaryOverviewVO.setNewPayUserChain(newPayUserChain);
        // 支付用户人数
        String totalPayUser = userSummaryOverviewVO.getTotalPayUser();
        // 上一周期支付用户人数
        String newtotalPayUser = userSummaryOverviewVO.getNewtotalPayUser();
        // 支付用户人数环比
        String totalPayUserChain = AmountUtils.getPercentage(newtotalPayUser, totalPayUser);
        userSummaryOverviewVO.setTotalPayUserChain(totalPayUserChain);
        // 新增用户转换率
        String userRepurchaseRate = userSummaryOverviewVO.getUserRepurchaseRate();
        // 上一周期新增用户转换率
        String userPreRepurchaseRate = userSummaryOverviewVO.getUserPreRepurchaseRate();
        // 新增用户转换率环比
        String userRepurchaseRateChain = AmountUtils
                .getPercentageSubtraction(userRepurchaseRate, userPreRepurchaseRate);
        userSummaryOverviewVO.setUserRepurchaseRateChain(userRepurchaseRateChain);
    }
}

 

以上是关于多线程在项目中的引用(CountDownLatch)的主要内容,如果未能解决你的问题,请参考以下文章

java多线程CountDownLatch

java多线程-CountDownLatch

CountDownLatch的用法及作用

Java并发包中CountDownLatch的工作原理使用示例

多线程与并发Java并发工具类

多线程 - CountDownLatch