多线程执行门店选品任务

1.背景

连锁零售公司旗下有1000家门店,每个门店的选品过程都是独立的,每个门店选品执行的时间平均为30秒,单线程串行执行所有门店选品需要500分钟,因为业务上下游给的时间有限,需要减少整体的执行时间,执行时间控制在100分钟内。

2.思路

并行执行,500/100=5,同时有五家门店在选品,单台机器并发执行的能力是有限,若超过单台机器的并发能力可以用定时任务分片的方式来扩展并发能力。

3.模拟代码

3.1.门店选品

/**
 * 门店选品
 *
public class StoreSelection {

    /**
     * 门店编码
     */
    private String storeCode;

    private final static String TXT = "门店选品开始门店选品开始门店选品开始门店选品开始门店选品开始门店选品开始门店选品开始门店选品开始门店选品开始";

    public StoreSelection(String storeCode) {
        this.storeCode = storeCode;
    }

    public String select(){
        System.out.println(String.format("%s门店编码=%s的门店选品开始",  LocalDateTime.now(), storeCode));
        Base64.Encoder encoder = Base64.getEncoder();
        LocalDateTime start = LocalDateTime.now();
        LocalDateTime end = start.plusSeconds(30);
        //模拟选品过程中有异常
        if ("A10".equals(storeCode)) {
            throw new RuntimeException(storeCode + "门店选品异常请处理");
        }
        while (LocalDateTime.now().isBefore(end)) {
            //加重CPU负载
            encoder.encode(TXT.getBytes());
            //System.out.println(String.format("%s门店编码=%s的门店选品执行中", LocalDateTime.now(), storeCode));
        }
        System.out.println(String.format("%s门店编码=%s的门店选品完成", LocalDateTime.now(), storeCode));
        return  storeCode + "门店选品完成";
    }

    public static void main( String[] args ) {
        new StoreSelection("A1").select();
    }
}

3.2.连锁零售公司旗下所有门店选品

public class GroupSelection{

    public static void main( String[] args ) {
        List<String> storeCodeList = new LinkedList<>();
        for (int i = 0; i < 1000; i++) {
            storeCodeList.add("A"+i);
        }
        System.out.println("门店组选品开始");
        ExecutorService executor = Executors.newFixedThreadPool(5);
        List<Future<String>> futureList = storeCodeList.stream()
                .map(storeCode -> executor.submit(() -> new StoreSelection(storeCode).select()))
                .collect(Collectors.toList());
        while(!futureList.stream().allMatch(Future::isDone)){
            System.out.println("等待所有门店选品执行结束");
        }
        String re  = futureList.stream().map(future -> {
            try {
                return future.get();
            } catch (ExecutionException | InterruptedException e) {
                e.printStackTrace();
                return e.getMessage();
            }
        }).collect(Collectors.joining(","));
        System.out.println(re);
        System.out.println("门店组选品完成");
        executor.shutdown();
    }

}

4.隐患

4.1.随着公司的扩张门店数,线程池里的队列膨胀,可能导致OOM

5.可改进

5.1 使用CompletableFuture

5.2 日志改用slf4j

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容