涛涛实习记录——词库导入优化

4 阅读1分钟

其实这种导入优化有点老生常谈了,感觉核心就两个:

1:大数据分批处理(分治)

2:充分利用线程池来多线程处理,比如我遇到的解析 excle,然后校验词条,然后批量导入,这里每一步都可以用多线程。

通用的处理方式应该就这样吧

/**
 * 导入黑名单词语列表,使用批处理和多线程方式
 * @param words 要导入的词语列表
 * @throws InterruptedException 如果等待过程被中断
 */
public void importBlacklistWords(List<String> words) throws InterruptedException {
    int totalWords = words.size();
    // 计算需要多少批次,向上取整确保所有词语都被处理
    int batchCount = (int) Math.ceil((double) totalWords / BATCH_SIZE);
    // 创建CountDownLatch用于同步所有批次的处理
    CountDownLatch latch = new CountDownLatch(batchCount);

    // 批量导入
    for (int i = 0; i < batchCount; i++) {
        // 计算每批的起始和结束索引
        int start = i * BATCH_SIZE;
        int end = Math.min(start + BATCH_SIZE, totalWords);
        // 获取当前批次的词语子列表
        List<String> batchWords = words.subList(start, end);

        // 提交线程池处理每批数据
        executorService.submit(() -> {
            // 检查当前操作是否有效(可能是检查系统状态或权限)
            if(valid()){
                try {
                    // 导入当前批次的词语
                    importBatch(batchWords);
                } catch (SQLException e) {
                    // 处理导入失败的情况
                    handleBatchFailure(batchWords);
                } finally {
                    // 无论成功与否,都减少等待计数
                    latch.countDown();
                }
            }
        });
    }

    // 等待所有批次处理完成,或者直到超时
    latch.await(TIMEOUT, TimeUnit.SECONDS);
    // 关闭线程池
    executorService.shutdown();
}