Java8 API文档搜索引擎_优化构建索引速度

作者:_周游日期:2026/2/3

本专栏前文已介绍完成索引模块程序:

https://blog.csdn.net/m0_63299495/article/details/157515700?spm=1011.2415.3001.5331https://blog.csdn.net/m0_63299495/article/details/157515700?spm=1011.2415.3001.5331并对关键部分进行了细节整理:

https://blog.csdn.net/m0_63299495/article/details/157516644?spm=1011.2415.3001.5331https://blog.csdn.net/m0_63299495/article/details/157516644?spm=1011.2415.3001.5331本文介绍优化点:优化构建索引速度。


目录

1. 验耗时

2. 多线程制作索引

2.1 关于CountDownLatch

2.2 关于线程加锁

2.3 关于守护线程

3. 修改后的Parser类的run方法


1. 验耗时

在Paser类中的run方法内打时间戳检验耗时操作:

1public void run(){
2        long beg = System.currentTimeMillis();
3        System.out.println("开始构造索引");
4
5        long Beg = System.currentTimeMillis();
6//        1、根据加载文档路径,枚举该路径目录及其子目录下的所有文件(html)
7        ArrayList<File> fileList=new ArrayList<>();
8        // INPUT-PATH表示开始进行递归遍历的起始目录
9        // fileList表示递归遍历的结果
10        enumFile(INPUT_PATH, fileList);
11        long enumFileEnd = System.currentTimeMillis();
12        System.out.println("枚举文件耗时:"+(enumFileEnd-Beg)+" ms");
13
14//        2、根据罗列出的文件路径打开文件,读取文件内容,进行解析并构建索引
15
16        for(File f: fileList){
17//            parseHTML方法用于解析单个HTML文件
18            System.out.println("开始解析 "+f.getAbsolutePath());
19            parseHTML(f);
20        }
21        long forEnd = System.currentTimeMillis();
22        System.out.println("遍历文件耗时:"+(forEnd-enumFileEnd)+" ms");
23//        3、把内存中构造的索引数据结构保存到指定文件中
24        index.save();
25        System.out.println("完成构造索引");
26        long end = System.currentTimeMillis();
27        System.out.println("构建索引耗时:"+(end - beg)+" ms ");
28    }

再次启动Paser类,获取耗时如下:

(省略中间各html文件的遍历输出结果)

可见在构建索引的枚举、遍历和保存三个操作中,遍历文件耗时占比最高,现基于该问题进行制作索引的优化,考虑使用多线程制作索引。

2. 多线程制作索引

2.1 关于CountDownLatch

CountDownLatch是一个同步辅助工具,允许一个或多个线程等待其他线程完成操作,其实现线程同步的思想是计数器思想,countDown方法实现减少计数器值,await方法实现等待计数器清零

通过submit向线程池里提交任务,只是把Runnable对象放到阻塞队列中,并不代表线程池中的文档在submit提交完成后也被全部解析完了。为了保证执行save时保存的是完整的解析后的全部文档,采用CountDownLatch的await方法来表示所有任务都完成。

2.2 关于线程加锁

在Index类中有一个addDoc方法,会调用buildForward方法和buildInverted方法,buildForward方法会修改forwardIndex,buildInverted方法会修改invertedIndex,四个线程并发调用addDoc时就存在线程安全问题,需要加锁来解决线程安全问题。

如果直接把synchronized加到parseHTML或addDoc上,加锁粒度太粗使得并发程度较低,需要再细致地考虑加锁的粒度。

在buildForwad方法中,设置docId和将新doc插入到正排索引中两个操作需要加锁:

1        synchronized (locker1){
2            docInfo.setDocId(forwardIndex.size());
3            forwardIndex.add(docInfo);
4        }

在buildInverted方法中,在倒排拉链中根据关键词去倒排索引中查找的结果的操作都需要加锁:

1 synchronized (locker2){
2                List<Weight> invertedList = invertedIndex.get(entry.getKey());
3                // 如果为空则插入新键值对
4                if(invertedList == null){
5                    ArrayList<Weight> newInvertedList = new ArrayList<>();
6                    // 把当前的文档信息docInfo构造成Weight对象
7                    Weight weight = new Weight();
8                    weight.setDocId(docInfo.getDocId());
9                    // 假定权重公式:标题中出现的次数*10+正文中出现的次数*1
10                    weight.setWeight(entry.getValue().titleCount*10+entry.getValue().contentCount);
11                    newInvertedList.add(weight);
12                    invertedIndex.put(entry.getKey(),newInvertedList);
13                }else{
14                    //非空则将当前文档信息docInfo构造成Weight对象插入倒排拉链
15                    Weight weight = new Weight();
16                    weight.setDocId(docInfo.getDocId());
17                    weight.setWeight(entry.getValue().titleCount*10+entry.getValue().contentCount);
18                    invertedList.add(weight);
19                }
20            }

且注意二者并不竞争同一锁资源,故创建的locker1和locker2为不同锁资源:

1    // 新创建两个锁对象
2    private Object locker1 = new Object();
3    private Object locker2 = new Object();

2.3 关于守护线程

如果一个线程是守护线程(后台线程),则这个线程的运行状态不会影响到进程结束。

如果一个线程不是守护线程,则这个线程的运行状态就会影响到进程结束。

之前我们采用的是线程池创建线程:

ExecutorService executorService = Executors.newFixedThreadPool(4);

默认创建出来的都是非守护线程,故当main方法执行完后这些线程仍然在等待新任务,并未终止,需要使用shutdown方法进行手动终止。

可见使用多线程后,构建索引耗时由17s将至7s,效率得到了提升。

3. 修改后的Parser类的run方法

1 /*
2    * 优化制作索引:多线程制作索引
3    * */
4    public void run() throws InterruptedException {
5        long beg = System.currentTimeMillis();
6        System.out.println("开始构建索引");
7        // 1. 枚举文件:
8        ArrayList<File> files = new ArrayList<>();
9        enumFile(INPUT_PATH, files);
10        // 2. 多线程循环遍历文件:
11        CountDownLatch latch = new CountDownLatch(files.size());
12        ExecutorService executorService = Executors.newFixedThreadPool(4);
13        for(File f: files){
14            // 通过submit向线程池里提交任务,只是把Runnable对象放到阻塞队列中
15            executorService.submit(new Runnable() {
16                @Override
17                public void run() {
18                    System.out.println("解析: "+f.getAbsolutePath());
19                    parseHTML(f);
20                    latch.countDown();
21                }
22            });
23        }
24        // 3. 待所有文件解析完成后再保存索引:
25        latch.await();
26        // 手动终止线程池中的所有线程
27        executorService.shutdown();
28        index.save();
29
30        long end = System.currentTimeMillis();
31        System.out.println("完成构建索引");
32        System.out.println("构建索引耗时:"+(end-beg)+" ms");
33    }
34

Java8 API文档搜索引擎_优化构建索引速度》 是转载文章,点击查看原文


相关推荐


Linux软件安装 —— Flink集群安装(集成Zookeeper、Hadoop高可用)
吱唔猪~2026/1/25

文章目录 一、节点说明二、配置节点间免密登录三、JDK安装四、Zookeeper安装五、Hadoop安装六、Flink安装1、基础环境准备(1)下载安装包(2)上传并解压 2、修改配置(1)配置zookeeper(2)配置flink-conf.yaml(3)配置workers(4)创建必要的目录(5)配置环境变量 3、分发flink 七、集群测试1、启动zookeeper,hadoop2、Yarn Session测试(1)模式介绍(2)准备测试资源


图解DeepSeek最新论文,人人都能看得懂!
饼干哥哥2026/1/16

DeepSeek 又发论文了。 这一次,没有惊天动地的参数军备竞赛,没有万卡集群的暴力美学。 他们只是冷静地指出了当前 AI 届一个“皇帝的新衣”: 我们最顶尖的大模型,其实都在做着极其愚蠢的事情。 在这篇名为《Conditional Memory via Scalable Lookup》(基于可扩展查找的条件记忆)的论文中,DeepSeek 创始人梁文锋亲自署名,揭示了下一代大模型架构(V4?)的核心秘密:与其让模型更努力地“思考”,不如教它学会“作弊”。 01.愚蠢的天才:为什么要用算力去


如何在CentOS 7.9 服务器上配置并优化 Ceph 分布式存储集群,提升数据冗余与性能?
A5IDCCOM2026/1/8

本文基于A5IDC在真实生产环境(跨机房 Ceph 集群支撑虚拟机盘、对象存储及容灾复制)的实战经验,详细讲解如何从零部署 Ceph 集群在 CentOS 7.9 上,并通过硬件配置选择、网络优化、Ceph 参数调优等实用细节提升 数据冗余能力与性能表现。文章包含具体产品型号、系统配置表、命令示例与性能评估对比表,适合中大型数据中心储存架构实施。 一、背景与目标 随着业务系统对海量数据持久层的要求不断提升,我们需要一个高可靠、易扩展、具有自动自愈能力的分布式存储平台。Ceph 是开源生态


Git/Gitee/GitHub有什么区别
lifewange2025/12/31

Git、GitHub、Gitee(码云)三者核心区别 & 完整详解 你想弄清楚这三者的关系和差异,本质上Git 是「工具」,GitHub/Gitee 是「平台」,这是最核心的定位区别,三者不是同一维度的东西,先把这个核心逻辑吃透,所有差异就一目了然了。 ✅ 一、三者的「本质定位」(最核心,必记) 1. Git —— 本地的「版本控制系统」(纯软件 / 工具) Git 是一个免费、开源的分布式版本控制软件,它是一个安装在你电脑本地的程序 / 工具,不依赖任何网络、不依赖任何网站就能独立运行


Apache Tika XXE注入漏洞 | CVE-2025-66516 复现&研究
探索宇宙真理.2025/12/21

0x0 背景介绍 Tika Pdf Parser Module是Apache软件基金会开发的Java库,专用于解析PDF文件内容。核心功能包括文本提取、元数据解析及嵌入式对象处理,基于Apache Tika框架实现,依赖PDFBox等开源库。 Apache Tika的tika-core(1.13-3.2.1)、tika-pdf-module(2.0.0-3.2.1)和tika-parsers(1.13-1.28.5)模块存在严重XXE漏洞(跨平台),攻击者可通过构造PDF内的XFA文件实施XM


tig 的untracked changes和unstaged changes含义?
aoxiang_ywj2025/12/13

背景:你理解tig中untracked changes和unstaged changes的含义?它们对应的代码存在哪里呢?在本地仓库?提交到gitlab线上库了?下面将解答这些疑问。 一、核心结论先明确 tig 中显示的 Untracked changes(未跟踪变更)和 Unstaged changes(未暂存变更)都属于本地工作区的修改,完全没有提交到 GitLab 线上库,甚至连「本地仓库的提交(commit)」都没完成 —— 它们和 GitLab 线上库没有任何关联,仅存在于你的本地


iOS内存映射技术:mmap如何用有限内存操控无限数据
sweet丶2025/12/5

当一个iOS应用需要处理比物理内存大10倍的文件时,传统方法束手无策,而mmap却能让它流畅运行。这种神奇能力背后,是虚拟内存与物理内存的精密舞蹈。 01 内存管理的双重世界:虚拟与物理的分离 每个iOS应用都生活在双重内存现实中。当你声明一个变量或读取文件时,你操作的是虚拟内存地址,这是iOS为每个应用精心编织的“平行宇宙”。 这个宇宙大小固定——在64位iOS设备上高达128TB的虚拟地址空间,远超任何物理内存容量。 虚拟内存的精妙之处在于:它只是一个巨大的、连续的地址范围清单,不直接对应


为什么 Memo Code 先做 CLI:以及终端输入框到底有多难搞
mCell2026/2/12

同步至个人站点:为什么 Memo Code 先做 CLI:以及终端输入框到底有多难搞 如果你对我的 Code Agent项目感兴趣,可以看这里: Github Repo: Memo Code - Github 站点:Memo Web Site 大概四年前,我刚接触编程。学的是 C 语言,第一个程序当然是 hello world。 很简单,几行就写完。run 一下,弹出来一个 terminal(我已经忘了当时用的是什么:cmd?PowerShell?反正不重要),然后打印了一行: “hell


花 200 美刀买“黑盒”?Claude Code 这波更新,把程序员当傻子了吧…
Dcs2026/2/21

有些产品吧,功能再强,只要开始“藏事儿”,程序员的雷达立马就响了: 你到底读了哪个文件?你到底搜了啥?你到底改了啥?——别跟我说“别管细节,反正我很聪明”。哥们,工程不是玄学,是可验证、可追溯、可复盘。 然后,Claude Code 2.1.20 就真把这事做了:把“读取文件路径”和“搜索 pattern”这种最基础的可观测信息,直接干没了。 1)更新前 vs 更新后:从“可审计”变成“随缘”🤡 以前你会看到它读了哪些文件、搜了什么关键词,属于那种一眼就能判断它有没有跑偏的“低噪音透明输出”


在OrangePi-5 Plus/5 Ultra上实时运行yolo26进行无人机检测,fps超50!
吃素的力2026/3/1

在OrangePi-5 Plus/5 Ultra上使用VideoPipe与YOLO26n实现高性能无人机检测 视频效果展示 RK3588无人机检测 前言 随着低空经济的快速发展,无人机检测已成为安防监控、边境巡逻、关键区域保护等场景中的重要需求。OrangePi 5 Plus和OrangePi 5 Ultra作为瑞芯微RK3588平台的高性能开发板,凭借其强大的NPU算力,成为边缘端AI推理的理想选择。 本文将详细介绍如何基于VideoPipe框架,结合最新的Y

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 XYZ博客