摘要

现在写crud越来越得心应手了,主要是在一个领域内重复,写久了,会发现万变不离其宗,但是偶尔也会遇到一点问题,虽然很快就能解决,还是觉得有必要分享一下。

正文

需求就是因为数据量过大,就实现一个类似于异步分批计算,最后再取回合并的功能。

但是直接使用subList,发现原数组的值被改了,简单的分析了一下代码。

java
1
2
tempList = list.subList(0, batchNumber);
tempList.clear();

是因为我对截取的List进行了清空处理,导致原List改变了,由此处也可知subList其实是指向了原List截取的部分,如果对他清除了,原List也就会改变了。

发现了这个原因,实现一个分批的功能就简单多了。

分批计算的是项目中的,比较复杂。

我下面以分批保存数据库为例,复现一下这个问题,这是一个完整的例子。

java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
 * 同步保存
 *
 * @param list
 */
private void batchSaveSync(List<Student> list) {
    int slice = slice(list.size(), batchNumber);
    for (int i = 0; i < slice; i++) {
        List<Student> tempList;
        if (batchNumber > list.size()) {
            //前闭后开
            tempList = list.subList(0, list.size());
        } else {
            tempList = list.subList(0, batchNumber);
        }
        crudRepository.saveAll(tempList);
        //因为SubList是指向的地址,如果将该区域清掉,原List也会受到影响,所以就可以继续使用subList从0开始
        tempList.clear();
    }
}

/**
 * 异步通过线程池保存
 *
 * @param list
 */
private void batchSaveAsync(List<Student> list) {
    ExecutorService executorService = new ExecutorConfig().executorService();
    int slice = slice(list.size(), batchNumber);
    for (int i = 0; i < slice; i++) {
        List<Student> tempList;
        if (batchNumber > list.size()) {
            //前闭后开
            tempList = list.subList(0, list.size());
        } else {
            tempList = list.subList(0, batchNumber);
        }
        BatchSaveCallable callable = new BatchSaveCallable(tempList);
        executorService.submit(callable);
        //因为SubList是指向的地址,如果将该区域清掉,原List也会受到影响,所以就可以继续使用subList从0开始
        tempList.clear();
    }
}


/**
 * 分组
 * [java分页算法 - SegmentFault 思否](https://segmentfault.com/a/1190000018350964)
 *
 * @param size
 * @param batchNumber
 * @return
 */
private Integer slice(int size, int batchNumber) {
    return (size - 1) / batchNumber + 1;
}

源码meethigher/batch-save: batch-save