当前位置: 首页 > news >正文

使用Apache Lucene构建高效的全文搜索服务

使用Apache Lucene构建高效的全文搜索服务

在现代应用程序中,全文搜索功能是不可或缺的一部分。无论是电子商务网站、内容管理系统,还是数据分析平台,快速、准确地搜索大量数据是提升用户体验的关键。Apache Lucene 是一个强大的全文搜索引擎库,它提供了高效的索引和搜索功能,能够轻松集成到Java应用程序中。本文将介绍如何使用Apache Lucene构建一个高效的全文搜索服务,并通过一个实际的Java代码示例来展示其核心功能。

1. Lucene简介

Apache Lucene 是一个高性能、全功能的文本搜索引擎库,使用Java编写。它提供了强大的索引和搜索功能,支持多种查询类型,如布尔查询、范围查询、模糊查询等。Lucene的核心优势在于其高效的索引结构和灵活的API,使得开发者可以轻松地构建复杂的搜索功能。

2. 项目结构

在这个示例中,我们将构建一个简单的搜索服务,用于索引和搜索拍卖交易历史记录(AtcoinDealhistory)。项目的主要类 LuceneService 负责管理索引的创建、更新和搜索操作。

3. 索引创建与更新

在Lucene中,索引的创建和更新是通过 IndexWriter 来完成的。IndexWriter 负责将文档(Document)添加到索引中,并确保索引的高效存储和检索。

public void indexDocument(List<AtcoinDealhistory> list) throws IOException {long startTime = System.currentTimeMillis(); // 记录开始时间// 配置IndexWriterIndexWriterConfig config = new IndexWriterConfig(analyzer);config.setMaxBufferedDocs(20); // 设置最大缓冲文档数config.setRAMBufferSizeMB(2048.0); // 设置RAM缓冲区大小config.setUseCompoundFile(true); // 使用复合文件格式// 使用try-with-resources确保IndexWriter正确关闭try (IndexWriter indexWriter = new IndexWriter(directory, config)) {for (AtcoinDealhistory atcoinDealhistory : list) {Document doc = new Document();if (atcoinDealhistory.getAuctionId() != null) {// 添加字段到文档doc.add(new StringField("id", atcoinDealhistory.getId().toString(), Store.YES));doc.add(new StringField("auction_id", atcoinDealhistory.getAuctionId(), Store.YES));doc.add(new TextField("auction_name", atcoinDealhistory.getAuctionName(), Store.YES));doc.add(new StringField("amount", atcoinDealhistory.getAmount(), Store.YES));doc.add(new TextField("data", atcoinDealhistory.getData(), Store.YES));doc.add(new StringField("picture", atcoinDealhistory.getPicture(), Store.YES));// 处理日期字段if (atcoinDealhistory.getDealdate() != null) {try {SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");String dateStr = dateFormat.format(atcoinDealhistory.getDealdate());// 添加日期字段,用于排序doc.add(new SortedNumericDocValuesField("date", atcoinDealhistory.getDealdate().getTime()));// 添加日期字段,用于存储doc.add(new StringField("dealdate", dateStr, Store.YES));} catch (Exception e) {e.printStackTrace();}}}// 将文档添加到索引indexWriter.addDocument(doc);indexWriter.commit(); // 提交更改}} catch (Exception e) {e.printStackTrace();}long endTime = System.currentTimeMillis(); // 记录结束时间System.out.println("Index creation time: " + (endTime - startTime) + " milliseconds");
}

在这个方法中,我们首先配置了 IndexWriter,然后遍历 AtcoinDealhistory 对象列表,将每个对象的字段添加到 Document 中,并将其写入索引。我们还处理了日期字段,确保它们可以用于排序和存储。

4. 搜索功能

Lucene 的搜索功能是通过 IndexSearcher 来实现的。IndexSearcher 负责执行查询并返回匹配的文档。我们可以使用多种查询类型来构建复杂的搜索条件。

public List<AtcoinDealhistory> search(AtcoinDealhistory atcoinDealhistory) throws IOException, org.apache.lucene.queryparser.classic.ParseException {List<AtcoinDealhistory> results = new ArrayList<>();long startTime = System.currentTimeMillis(); // 记录开始时间// 打开索引目录try (DirectoryReader reader = DirectoryReader.open(directory)) {IndexSearcher searcher = new IndexSearcher(reader);BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder();// 处理日期范围查询String startQueryDealDate = atcoinDealhistory.getStartQueryDealDate();String endQueryDealDate = atcoinDealhistory.getEndQueryDealDate();if (startQueryDealDate != null && endQueryDealDate != null) {TermRangeQuery dateRangeQuery = TermRangeQuery.newStringRange("dealdate", startQueryDealDate, endQueryDealDate, true, true);booleanQueryBuilder.add(dateRangeQuery, Occur.MUST);}// 处理金额范围查询Integer startQueryAmount = atcoinDealhistory.getStartQueryAmount();Integer endQueryAmount = atcoinDealhistory.getEndQueryAmount();if (startQueryAmount != null && endQueryAmount != null) {TermRangeQuery amountRangeQuery = TermRangeQuery.newStringRange("amount", Integer.toString(startQueryAmount), Integer.toString(endQueryAmount), true, true);booleanQueryBuilder.add(amountRangeQuery, Occur.MUST);}// 处理拍卖名称的关键词查询List<String> terms = analyzeQueryString(analyzer, atcoinDealhistory.getAuctionName());for (String term : terms) {TermQuery termQuery = new TermQuery(new Term("auction_name", term));booleanQueryBuilder.add(termQuery, Occur.MUST);}// 设置排序规则,根据日期字段降序排列SortField sortDate = new SortField("date", SortField.Type.LONG, true);Sort sort = new Sort(SortField.FIELD_SCORE, sortDate);// 执行查询ScoreDoc[] hits = searcher.search(booleanQueryBuilder.build(), 100, sort).scoreDocs;SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");// 遍历查询结果for (ScoreDoc hit : hits) {Document doc = searcher.doc(hit.doc);AtcoinDealhistory result = new AtcoinDealhistory();result.setId(Long.valueOf(doc.get("id")));result.setAuctionId(doc.get("auction_id"));result.setAuctionName(doc.get("auction_name"));result.setAmount(doc.get("amount"));result.setData(doc.get("data"));result.setPicture(doc.get("picture"));// 处理日期字段if (doc.get("dealdate") != null) {try {Date dealdate = dateFormat.parse(doc.get("dealdate"));result.setDealdate(dealdate);} catch (Exception e) {e.printStackTrace();}}results.add(result);}}long endTime = System.currentTimeMillis(); // 记录结束时间System.out.println("Index search time: " + (endTime - startTime) + " milliseconds");return results;
}

在这个方法中,我们首先打开索引目录并创建 IndexSearcher。然后,我们构建了一个布尔查询(BooleanQuery),用于处理日期范围、金额范围和关键词查询。最后,我们执行查询并遍历结果,将匹配的文档转换为 AtcoinDealhistory 对象并返回。

5. 分词器

Lucene 的分词器(Analyzer)用于将文本分解为单词或词语。在这个示例中,我们使用了 StandardAnalyzer,它是Lucene提供的一个标准分词器,适用于大多数英文文本。

	public LuceneService() throws IOException {// 索引目录的路径this.directory = FSDirectory.open(Paths.get(INDEX_DIR));// 标准索引解析器this.analyzer = new StandardAnalyzer();// 第三方分词器解析器
//		this.analyzer = new ReIKAnalyzer(false);}
public List<String> analyzeQueryString(Analyzer analyzer, String queryString) throws IOException {List<String> terms = new ArrayList<>();// 使用分词器处理查询字符串try (TokenStream tokenStream = analyzer.tokenStream("auction_name", new StringReader(queryString))) {CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);tokenStream.reset();// 遍历分词结果while (tokenStream.incrementToken()) {terms.add(charTermAttribute.toString());}tokenStream.end();}return terms;
}

这个方法将查询字符串分解为多个词语,并将它们添加到列表中,以便在搜索时使用。

6. 总结

通过这个示例,我们展示了如何使用Apache Lucene构建一个高效的全文搜索服务。Lucene提供了强大的索引和搜索功能,使得开发者可以轻松地处理复杂的搜索需求。无论是处理结构化数据还是非结构化文本,Lucene都能提供高效的解决方案。

7. 附录

maven 依赖

<!-- 搜索模块 --><!-- Lucene Core Dependency --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-core</artifactId><version>8.11.0</version> <!-- 请根据需要选择合适的版本 --></dependency><!-- Lucene Analyzers Dependency --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers-common</artifactId><version>8.11.0</version></dependency><!-- 如果需要其他Lucene模块,也可以继续添加 --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-queryparser</artifactId><version>8.11.0</version></dependency><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-highlighter</artifactId><version>8.11.0</version></dependency><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-memory</artifactId><version>8.11.0</version></dependency><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-queries</artifactId><version>8.11.0</version></dependency><!-- <dependency><groupId>org.truenewx</groupId><artifactId>ik-analyzer-lucene</artifactId><version>5.0.1</version></dependency>--><dependency><groupId>com.github.keran213539</groupId><artifactId>IK_Analyzer</artifactId><version>2012FF_hf1_1</version></dependency><!-- https://mvnrepository.com/artifact/org.ansj/ansj_seg --><!-- <dependency><groupId>org.ansj</groupId><artifactId>ansj_seg</artifactId><version>5.1.6</version></dependency>-->

多线程索引创建

索引创建的时间有点久了,增加多线程处理

// 创建或更新索引public void indexDocument(List<AtcoinDealhistory> list) throws IOException {long startTime = System.currentTimeMillis(); // 记录开始时间//引入多线程ExecutorService executorService = Executors.newFixedThreadPool(numThreads);try {for (AtcoinDealhistory atcoinDealhistory : list) {executorService.submit(() -> {try {indexDocument(this.directory,this.analyzer,atcoinDealhistory);} catch (IOException e) {e.printStackTrace();}});}executorService.shutdown();executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);long endTime = System.currentTimeMillis(); // 记录结束时间// 计算索引创建时间long indexCreationTime = endTime - startTime;System.out.println("Index creation time: " + indexCreationTime/1000 + " milliseconds");} catch (Exception e) {System.out.println(e.getMessage());e.printStackTrace();} }

IK分词器重写

因为Lucene版本问题,IKAnalyzer 需要进行重写

package com.atcoin.busi.test;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Tokenizer;
import org.wltea.analyzer.cfg.Configuration;public class ReIKAnalyzer extends Analyzer {private boolean useSmart;//分词器配置项private Configuration cfg;public Configuration getCfg() {return cfg;}public void setCfg(Configuration cfg) {this.cfg = cfg;}public boolean useSmart() {return useSmart;}public void setUseSmart(boolean useSmart) {this.useSmart = useSmart;}/*** IK分词器Lucene 5.4.0 Analyzer接口实现类** 默认细粒度切分算法*/public ReIKAnalyzer() {this(false);}/*** IK分词器Lucene 5.4.0 Analyzer接口实现类** @param useSmart*            当为true时,分词器进行智能切分*/public ReIKAnalyzer(boolean useSmart) {super();this.useSmart = useSmart;}/*** IK分词器Lucene 5.4.0 Analyzer接口实现类** @param cfg*/public ReIKAnalyzer(Configuration cfg) {super();this.setCfg(cfg);}/*** 重载Analyzer接口,构造分词组件** @param fieldName*            the name of the fields content passed to the*            TokenStreamComponents sink as a reader*/@Overrideprotected TokenStreamComponents createComponents(String fieldName) {Tokenizer _IKTokenizer = new ReIKTokenizer(this.useSmart());return new TokenStreamComponents(_IKTokenizer);}}
package com.atcoin.busi.test;
import java.io.IOException;import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
import org.wltea.analyzer.cfg.Configuration;
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;public class ReIKTokenizer extends Tokenizer {// IK分词器实现private IKSegmenter _IKImplement;// 词元文本属性private final CharTermAttribute termAtt;// 词元位移属性private final OffsetAttribute offsetAtt;// 词元分类属性(该属性分类参考org.wltea.analyzer.core.Lexeme中的分类常量)private final TypeAttribute typeAtt;// 记录最后一个词元的结束位置private int endPosition;/*** Lucene 5.4.0 Tokenizer适配器类构造函数** @param in* @param useSmart*/public ReIKTokenizer(boolean useSmart) {super();offsetAtt = addAttribute(OffsetAttribute.class);termAtt = addAttribute(CharTermAttribute.class);typeAtt = addAttribute(TypeAttribute.class);_IKImplement = new IKSegmenter(input, useSmart);}/*** Lucene 5.4.0 Tokenizer适配器类构造函数** @param in* @param cfg*/public ReIKTokenizer(Configuration cfg) {super();offsetAtt = addAttribute(OffsetAttribute.class);termAtt = addAttribute(CharTermAttribute.class);typeAtt = addAttribute(TypeAttribute.class);_IKImplement = new IKSegmenter(input, cfg);}@Overridepublic boolean incrementToken() throws IOException {// 清除所有的词元属性clearAttributes();Lexeme nextLexeme = _IKImplement.next();if (nextLexeme != null) {// 将Lexeme转成Attributes// 设置词元文本termAtt.append(nextLexeme.getLexemeText());// 设置词元长度termAtt.setLength(nextLexeme.getLength());// 设置词元位移offsetAtt.setOffset(nextLexeme.getBeginPosition(),nextLexeme.getEndPosition());// 记录分词的最后位置endPosition = nextLexeme.getEndPosition();// 记录词元分类typeAtt.setType(nextLexeme.getLexemeTypeString());// 返会true告知还有下个词元return true;}// 返会false告知词元输出完毕return false;}@Overridepublic void reset() throws IOException {super.reset();_IKImplement.reset(input);}@Overridepublic final void end() {// set final offsetint finalOffset = correctOffset(this.endPosition);offsetAtt.setOffset(finalOffset, finalOffset);}
}

接口调用

package com.atcoin.busi.controller;
import java.io.IOException;
import java.util.List;import javax.annotation.PreDestroy;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import com.atcoin.busi.domain.AtcoinDealhistory;
import com.atcoin.busi.service.IAtcoinDealhistoryService;
import com.atcoin.busi.service.impl.LuceneService;@RestController
@RequestMapping("/lucene")
public class AtcoinLuceneController {@Autowiredprivate IAtcoinDealhistoryService atcoinDealhistoryService;@Autowiredprivate LuceneService luceneService;//    @PostMapping("/index")
//    public String indexDocument(@RequestParam String id, @RequestParam String content) {
//        try {
//            luceneService.indexDocument(id, content);
//            return "Document indexed successfully.";
//        } catch (IOException e) {
//            e.printStackTrace();
//            return "Failed to index document.";
//        }
//    }@GetMapping("/createIndex")public String createIndex() {try {List<AtcoinDealhistory> list = atcoinDealhistoryService.selectAtcoinDealhistoryIndex();luceneService.indexDocument(list);return "Document indexed successfully.";} catch (IOException e) {e.printStackTrace();return "Failed to index document.";}}@GetMapping("/search")public List<AtcoinDealhistory> search(@RequestParam String keywords) {try {return luceneService.search(keywords);} catch (IOException | org.apache.lucene.queryparser.classic.ParseException e) {e.printStackTrace();return null;}}// 在应用关闭时关闭Lucene资源@PreDestroypublic void close() {try {luceneService.close();} catch (IOException e) {e.printStackTrace();}}
}

相关文章:

使用Apache Lucene构建高效的全文搜索服务

使用Apache Lucene构建高效的全文搜索服务 在现代应用程序中&#xff0c;全文搜索功能是不可或缺的一部分。无论是电子商务网站、内容管理系统&#xff0c;还是数据分析平台&#xff0c;快速、准确地搜索大量数据是提升用户体验的关键。Apache Lucene 是一个强大的全文搜索引擎…...

SSH远程登录并执行命令

SSH远程登录并执行命令 1、登录远程服务器2、远程执行命令3、远程执行交互命令4、远程执行脚本5、退出远程SSH连接 SSH是Linux中的远程连接管理工具&#xff0c;可以在本地服务器上通过SSH协议连接到远程服务器&#xff0c;并在远程服务器上执行命令 SSH不仅可以用来登录远程服…...

EasyRTC:支持任意平台设备的嵌入式WebRTC实时音视频通信SDK解决方案

随着互联网技术的飞速发展&#xff0c;实时音视频通信已成为各行各业数字化转型的核心需求之一。无论是远程办公、在线教育、智慧医疗&#xff0c;还是智能安防、直播互动&#xff0c;用户对低延迟、高可靠、跨平台的音视频通信需求日益增长。 一、WebRTC与WebP2P&#xff1a;实…...

Golang语言特性

1.Go语言的优势 1.1极简单的部署方式 —可以直接编译成机器码。代码可以直接转换为二进制数据&#xff0c;在操作系统上可以直接./去执行。 —不依赖其他库。最终生成的可执行程序是一个静态的二进制文本文件。 —可以直接运行即可部署。 —静态类型语言。编译的时候检查出来隐…...

LangPrompt提示词

LangPrompt提示词 https://github.com/langgptai/LangGPT 学习LangGPT的仓库&#xff0c;帮我创建 一个专门生成LangGPT格式prompt的助手 根据LangGPT的格式规范设计的专业提示词生成助手框架。以下是分步骤的解决方案&#xff1a; 助手角色定义模板 # Role: LangGPT提示词架…...

Java 容器之 List

在 Java 的集合框架中&#xff0c;List 是 Collection 的重要子接口&#xff0c;以其有序、可重复的特点广泛应用于开发中。本文将详细探讨 List 的核心概念、主要实现类&#xff08;如 ArrayList 和 LinkedList&#xff09;的底层原理&#xff0c;以及使用中需要注意的常见问题…...

ETL-kettle数据转换使用详解

一、excel转换成mysql 表格就按照我们刚才转换的表格来转换成MySQL数据 在MySQL数据库中创建数据库&#xff0c;这个根据自身情况。我就在现有test库中测试了。 根据以上步骤&#xff0c;新建转换。 构建流程图&#xff0c;选择excel输入和表输出 将两个组件连接起来 双击…...

【容器化】低版本docker拉取ubuntn 22.04镜像启动容器执行apt update提示 NO_PUBKEY 871920D1991BC93C

前置信息 宿主机信息 [root@localhost ~]# cat /etc/os-release NAME="CentOS Linux" VERSION="7 (Core)" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="7" PRETTY_NAME="CentOS Linux 7 (Core)" ANSI_COLOR…...

Hive-04之存储格式、SerDe、企业级调优

一、主题 hive表的数据压缩和文件存储格式hive的自定义UDF函数hive的JDBC代码操作hive的SerDe介绍和使用hive的优化 二、要点 1. hive表的文件存储格式 Hive支持的存储数的格式主要有&#xff1a;TEXTFILE&#xff08;行式存储&#xff09; 、SEQUENCEFILE(行式存储)、ORC&…...

Makefile、Make和CMake:构建工具的三剑客

目录 1. Makefile 2. Make 3. CMake Makefile、Make、CMake的关系 在软件开发中&#xff0c;构建工具是必不可少的。它们帮助开发者自动化编译、链接和打包的过程&#xff0c;确保代码能够高效地转化为可执行文件。Makefile、Make和CMake是三个常见的构建工具&#xff0c;它…...

The “Rule-of-Zero“ should be followed (s4963)

Most classes should not directly handle resources, but instead, use members that perform resource handling for them: For memory, it can be std::unique_ptr, std::shared_ptr, std::vector…​For files, it can be std::ofstream, std::ifstream…​…​ Classes …...

Kotlin语言特性(二):泛型与注解

Kotlin语言特性(二):泛型与注解 一、引言 在上一篇文章中,我们介绍了Kotlin的三大核心特性。本文将深入探讨Kotlin的泛型和注解特性,并与Java进行对比,帮助你更好地理解和运用这些特性。 二、Kotlin泛型 2.1 泛型基础 2.1.1 声明泛型类 // Kotlin泛型类声明 class …...

FunPapers[3]:WWW‘25「快手」生成式回归预测观看时长

Sequence Generation Modeling for Continuous Value Prediction https://arxiv.org/pdf/2412.20211&#xff0c;www 2025. 文章目录 Sequence Generation Modeling for Continuous Value Prediction核心思想1. CVP常规方法是怎么做的&#xff1f;2. 观看时长预测和CVP是如何关…...

并发编程1

JAVA线程回顾 多线程 多个并行的线程来完成个自的任务&#xff0c;优点是程序响应速度更快&#xff0c;程序性能得到提升。 并行执行与并发执行 并发执行就是在单核CPU下&#xff0c;现成实际上是串行执行的&#xff0c;任务调度器将cpu的时间片分给不同的线程使用&#xff0…...

Hadoop之01:HDFS分布式文件系统

HDFS分布式文件系统 1.目标 理解分布式思想学会使用HDFS的常用命令掌握如何使用java api操作HDFS能独立描述HDFS三大组件namenode、secondarynamenode、datanode的作用理解并独立描述HDFS读写流程HDFS如何解决大量小文件存储问题 2. HDFS 2.1 HDFS是什么 HDFS是Hadoop中的一…...

从源到目标:深度学习中的迁移学习与领域自适应实践

云边有个稻草人-CSDN博客 目录 引言 一、迁移学习概述 1.1 迁移学习的类型 1.2 迁移学习的核心思想 1.3 迁移学习的应用场景 二、领域自适应&#xff08;Domain Adaptation&#xff09; 2.1 领域自适应的定义 2.2 领域自适应的挑战 2.3 领域自适应的核心方法 &#…...

WebRTC与PJSIP:呼叫中心系统技术选型指南

助力企业构建高效、灵活的通信解决方案 在数字化时代&#xff0c;呼叫中心系统的技术选型直接影响客户服务效率和业务扩展能力。WebRTC与PJSIP作为两大主流通信技术&#xff0c;各有其核心优势与适用场景。本文从功能、成本、开发门槛等维度为您深度解析&#xff0c;助您精准匹…...

使用IDEA如何隐藏文件或文件夹

选择file -> settings 选择Editor -> File Types ->Ignored Files and Folders (忽略文件和目录) 点击号就可以指定想要隐藏的文件或文件夹...

【人工智能】数据挖掘与应用题库(1-100)

1、涉及变化快慢的问题可以考虑使用导数来分析。 答案:对 2、导数的几何意义是曲线在某点处切线的斜率。 答案:对 3、函数在某点的左导数存在,则导数就存在。 答案:错 4、关于梯度下降算法,下列说法错误的是( ) 错误:梯度下降算法能找到函数精确的最小值。 5、正…...

腾讯云大模型知识引擎驱动的DeepSeek满血版医疗顾问大模型搭建实战

文章目录 1. 引言2. 什么是腾讯云大模型知识引擎&#xff08;LKE&#xff09;&#xff1f;核心优势功能特点应用场景 3. 模型搭建过程3.1 注册登录产品3.2 创建应用3.3 配置模型3.4 配置角色指令3.5 配置欢迎语3.6 配置知识库3.7 配置工作流3.8 启用联网搜索3.9 发布模型 4. 问…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能&#xff1a;服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...