Java.mob.org.cn搜索_探讨Android全文检索技术

article/2025/8/23 13:23:23

原标题:探讨Android全文检索技术

写在前面

客户端本地存储数据一般使用的存储方式是:文件、SharedPreference、数据库(SQLite)

如果我们要做一些查询的操作,对于文件的方式,通过序列化和反序列化来进行数据的增删改查操作,表示效率低且繁琐到力不从心。

要实现高效的全文检索,必然需要使用到数据库,而对于手机客户端而言,SQLite支持FTS当然身先士卒

全文检索主要工作原理是:先建立索引,然后再对索引进行搜索

创建索引和搜索索引一般都是根据实际的业务进行相关设计的,没有全能的,只有相对和针对;至于优化,更是根据相关场景和数据量进行查询测试和分析的。

所以下面主要还是以介绍检索功能为出发点,来看看在实现全文检索的过程中,我们会遇到哪些知识分子,以及我们该如何吸收他们产出的能量。

通过这个篇文章你可以了解到:1. 全文检索是如何实现的

2. 全文检索涉及到的索引、倒排索引、B-树等等相关知识概念

3. 在Android端如何去使用全文检索功能

Sqlite FTS Extension

SQLite FTS Extension 是SQLite实现全文检索功能的插件。

目前一共有5个版本,其中FTS1、FTS2已经被废弃了,可用的版本为FTS3、FTS4、FTS5。

FTS3从SQLite 3.5.0版本开始支持

FTS4从SQLite 3.7.4版本开始支持

FTS5从SQLite 3.9.0版本开始支持

Sqlite在Android平台上对应的版本关系如下:

385d49ac7e7737fa1a95066b0ce26879.png

鉴于版本兼容,FTS5在Android 7.0及之后才开始支持,而目前市场上还有很大一部分机器是在7.0以下的,所以对于APP我们应该考虑使用FTS4。

那么下面我们主要以FTS4的身份,去分析和实现全文检索的功能

FTS 概要

FTS是SQLite数据库的虚拟表模块,提供全文检索的功能。

其基本增删改查操作方式如下:

//创建虚拟表fts_test

CREATEVIRTUALTABLEfts_test USING fts4(title, body, tokenize=unicode61);

//插入数据

INSERTINTOfts_test(title, body)VALUES('标题1','Java是全世界最好的编程语言');

//更新数据

UPDATEfts_testSETtitle ='标题1修正'WHERErowid = 1;

//根据rowid查询数据

SELECT*FROMfts_testWHERErowid = 1;

//全文检索数据

SELECT*FROMfts_testWHEREfts_test MATCH'java*';

//删除表数据

DELETEFROMfts_test;

//删除表结构

DROPTABLEfts_test;

FTS工作原理

其基本的工作原理如下:

854a540350828292a514db9686e9c0b2.png

其中分词器和倒排索引是关键

分词器

FTS4提供了四种系统分词器:simple、porter、icu、unicode61

类型

描述

simple根据单词进行分词,不区分大小写且不支持中文porter与simple一样,但是不区分单词语义(搜索do时,能搜索到do、did、does)icu将输入文本根据ICU规则寻找单词边界和丢弃任何标记,支持中文,可拓展unicode61根据空格和标点符号进行分词,依赖于Unicode Version 6.1标准,支持中文

使用方式:

CREATE VIRTUAL TABLE fts_test USING fts4(title, body, tokenize=unicode61);

当然也可以自定义分词器,这个需要在C层实现。

索引

是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是一种数据结构。

索引会增加表的体积,其实是在改变表的存储结构

主键是聚集索引,将表的存储结构变成了平衡树

创建其他索引会添加其他独立的索引结构,每次通过索引查询时,都会先去索引结构中查找到对应的主键,然后在通过主键去查找对应的内容

覆盖索引,即在多个字段上创建索引,这样可以通过索引直接查询到字段内容,加快了速度

索引虽然有效的提高的查询速度,但是也会影响数据的增删操作,所以需要根据具体情况做相关的决断

倒排索引

倒排索引源于实际应用中需要根据属性的值来查找记录。这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。

它是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。它是文档检索系统中最常用的数据结构。通过倒排索引,可以根据单词快速获取包含这个单词的文档列表。倒排索引主要由两个部分组成:“单词词典”和“倒排文件”。

倒排文件

用记录的非主属性值(也叫副键)来查找记录而组织的文件叫倒排文件,即次索引。倒排文件中包括了所有副键值,并列出了与之有关的所有记录主键值,主要用于复杂查询。

单词词典(难点)

是由文档集合中出现过的所有单词构成的字符串集合,单词词典内每条索引项记载单词本身的一些信息以及指向“倒排列表”的指针。(常用的数据结构包含哈希加链表和树形词典结构)

倒排列表

记载了出现过某个单词的所有文档的文档列表及单词在该文档中出现的位置信息,通过它可获知哪些文档包含某个单词

工作原理分析:

创建表的代码:

/*

** Create the backing store tables (%_content, %_segments and %_segdir)

** required by the FTS3 table passed as the only argument. This is done

** as part of the vtab xCreate() method.

**

** If the p->bHasDocsize boolean is true (indicating that this is an

** FTS4 table, not an FTS3 table) then also create the %_docsize and

** %_stat tables required by FTS4.

*/

staticintfts3CreateTables(Fts3Table *p){

intrc = SQLITE_OK; /* Return code */

inti; /* Iterator variable */

sqlite3 *db = p->db; /* The database connection */

if( p->zContentTbl==0 ){

constchar*zLanguageid = p->zLanguageid;

char*zContentCols; /* Columns of %_content table */

/* Create a list of user columns for the content table */

zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY");

for(i=0; zContentCols && inColumn; i++){

char*z = p->azColumn[i];

zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z);

}

if( zLanguageid && zContentCols ){

zContentCols = sqlite3_mprintf("%z, langid", zContentCols, zLanguageid);

}

if( zContentCols==0 ) rc = SQLITE_NOMEM;

/* Create the content table */

fts3DbExec(&rc, db,

"CREATE TABLE %Q.'%q_content'(%s)",

p->zDb, p->zName, zContentCols

);

sqlite3_free(zContentCols);

}

/* Create other tables */

fts3DbExec(&rc, db,

"CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);",

p->zDb, p->zName

);

fts3DbExec(&rc, db,

"CREATE TABLE %Q.'%q_segdir'("

"level INTEGER,"

"idx INTEGER,"

"start_block INTEGER,"

"leaves_end_block INTEGER,"

"end_block INTEGER,"

"root BLOB,"

"PRIMARY KEY(level, idx)"

");",

p->zDb, p->zName

);

if( p->bHasDocsize ){

fts3DbExec(&rc, db,

"CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);",

p->zDb, p->zName

);

}

assert( p->bHasStat==p->bFts4 );

if( p->bHasStat ){

sqlite3Fts3CreateStatTable(&rc, p);

}

returnrc;

}

1. 创建虚拟表并插入数据

sqlite> CREATE VIRTUAL TABLE fts_test USING fts4(title, body, tokenize='unicode61');

sqlite> INSERT INTO fts_test(title, body) VALUES('标题1','Java是全世界最好的变成语言');

sqlite> INSERT INTO fts_test(title, body) VALUES('标题2','Android是最牛逼的手机系统');

sqlite> INSERT INTO fts_test(title, body) VALUES('标题3','Java是Android应用层的主要编程语言');

2. 通过sqlite3查看表结构和表数据插入过程

sqlite> .table

看到共创建了如下6个表:

fts_test、fts_test_content、fts_test_segments、fts_test_segdir、fts_test_stat、fts_test_docsize

sqlite> SELECT * FROM sqlite_master WHERE type = "table";

可以看到表结构如下:

table|fts_test|fts_test|0|CREATE VIRTUAL TABLE fts_test using fts4(title, body)

table|fts_test_content|fts_test_content|5|CREATE TABLE 'fts_test_content'(docid INTEGER PRIMARY KEY, 'c0title', 'c1body')

table|fts_test_segments|fts_test_segments|6|CREATE TABLE 'fts_test_segments'(blockid INTEGER PRIMARY KEY, block BLOB)

table|fts_test_segdir|fts_test_segdir|7|CREATE TABLE 'fts_test_segdir'(level INTEGER,idx INTEGER,start_block INTEGER,leaves_end_block INTEGER,end_block INTEGER,root BLOB,PRIMARY KEY(level, idx))

table|fts_test_docsize|fts_test_docsize|9|CREATE TABLE 'fts_test_docsize'(docid INTEGER PRIMARY KEY, size BLOB)

table|fts_test_stat|fts_test_stat|10|CREATE TABLE 'fts_test_stat'(id INTEGER PRIMARY KEY, value BLOB)

sqlite> .dump

看到其插入数据的过程:

PRAGMA foreign_keys=OFF;

BEGIN TRANSACTION;

CREATE TABLE android_metadata (locale TEXT);

INSERT INTO android_metadata VALUES('zh_CN');

PRAGMA writable_schema=ON;

INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)VALUES('table','fts_test','fts_test',0,'CREATE VIRTUAL TABLE fts_test using fts4(title, body)');

CREATE TABLE IF NOT EXISTS 'fts_test_content'(docid INTEGER PRIMARY KEY, 'c0title', 'c1body');

INSERT INTO fts_test_content VALUES(1,'标题1','Java是全世界最好的编程语言');

INSERT INTO fts_test_content VALUES(2,'标题2','Android是最牛逼的手机系统');

INSERT INTO fts_test_content VALUES(3,'标题3','Java是Android应用层的主要编程语言');

CREATE TABLE IF NOT EXISTS 'fts_test_segments'(blockid INTEGER PRIMARY KEY, block BLOB);

CREATE TABLE IF NOT EXISTS 'fts_test_segdir'(level INTEGER,idx INTEGER,start_block INTEGER,leaves_end_block INTEGER,end_block INTEGER,root BLOB,PRIMARY KEY(level, idx));

INSERT INTO fts_test_segdir VALUES(0,0,0,0,'0 58',X’00256a617661e698afe585a8e4b896e7958ce69c80e5a5bde79a84e58f98e68890e8afade8a8800501010102000007e6a087e9a2983103010200');

INSERT INTO fts_test_segdir VALUES(0,1,0,0,'0 55',X’0022616e64726f6964e698afe69c80e7899be980bce79a84e6898be69cbae7b3bbe7bb9f0502010102000007e6a087e9a2983203020200');

INSERT INTO fts_test_segdir VALUES(0,2,0,0,'0 65',X’002c6a617661e698af616e64726f6964e5ba94e794a8e5b182e79a84e4b8bbe8a681e7bc96e7a88be8afade8a8800503010102000007e6a087e9a2983303030200');

CREATE TABLE IF NOT EXISTS 'fts_test_docsize'(docid INTEGER PRIMARY KEY, size BLOB);

INSERT INTO fts_test_docsize VALUES(1,X'0101');

INSERT INTO fts_test_docsize VALUES(2,X'0101');

INSERT INTO fts_test_docsize VALUES(3,X'0101');

CREATE TABLE IF NOT EXISTS 'fts_test_stat'(id INTEGER PRIMARY KEY, value BLOB);

INSERT INTO fts_test_stat VALUES(0,X'0303038801');

PRAGMA writable_schema=OFF;

COMMIT;

3. 表结构和内容分析

fts_test_content:存储的是完整的数据信息,默认会创建一个docid的主键

CREATE TABLE IF NOT EXISTS 'fts_test_content'(docid INTEGER PRIMARY KEY, 'c0title', 'c1body');

sqlite> select * from fts_test_content;

内容如下:

docid|c0title|c1body

1|标题1|Java是全世界最好的变成语言

2|标题2|Android是最牛逼的手机系统

3|标题3|Java是Android应用层的主要编程语言

fts_test_stat:存储的是FTS table的行数,以及表中所有行和列的符号总数

CREATE TABLE IF NOT EXISTS 'fts_test_stat'(id INTEGER PRIMARY KEY, value BLOB);

sqlite> select * from fts_test_stat;

内容如下:

id|value

0|0303038801

fts_test_docsize:存储的是docid以及每一行对列的tokens的数量(docid对应数据的所有符号数)

CREATE TABLE IF NOT EXISTS 'fts_test_docsize'(docid INTEGER PRIMARY KEY, size BLOB);

INSERT INTO fts_test_docsize VALUES(1,X'0101');

INSERT INTO fts_test_docsize VALUES(2,X'0101');

INSERT INTO fts_test_docsize VALUES(3,X'0101’);

sqlite> select * from fts_test_docsize;

内容如下:

docid|size

1|0101

2|0101

3|0101

fts_test_segments:保存B-树的非根节点(存储的是全文索引)

CREATE TABLE IF NOT EXISTS 'fts_test_segments'(blockid INTEGER PRIMARY KEY, block BLOB);

sqlite> select * from fts_test_segments;

内容无

fts_test_segdir:保存B-树的根节点(存储的是全文索引)

CREATE TABLE IF NOT EXISTS 'fts_test_segdir'(level INTEGER,idx INTEGER,start_block INTEGER,leaves_end_block INTEGER,end_block INTEGER,root BLOB,PRIMARY KEY(level, idx));

对应的字段含义如下:

2ce9211aa124e6f1893e9565db71d1af.png

插入数据的语句:

INSERT INTO fts_test_segdir VALUES(0,0,0,0,'0 58',X’00256a617661e698afe585a8e4b896e7 958ce69c80e5a5bde79a84e58f98e68890e8afade8a8800501010102000007e6a087e9a2983103010200');

INSERT INTO fts_test_segdir VALUES(0,1,0,0,'0 55',X’0022616e64726f6964e698afe69c80e7

899be980bce79a84e6898be69cbae7b3bbe7bb9f0502010102000007e6a087e9a2983203020200');

INSERT INTO fts_test_segdir VALUES(0,2,0,0,'0 65',X’002c6a617661e698af616e64726f6964e5ba94e7

94a8e5b182e79a84e4b8bbe8a681e7bc96e7a88be8afade8a8800503010102000007e6a087e9a2983303030200');

sqlite> select * from fts_test_segdir;

level|idx|start_block|leaves_end_block|end_block|root

0|0|0|0|0 58|00256a617661e698afe585a8e4b896e7

0|1|0|0|0 55|0022616e64726f6964e698afe69c80e7

0|2|0|0|0 65|002c6a617661e698af616e64726f6964

在Android中的使用姿势

DataDB

packagecom.mob.demo.ftsdb;

importandroid.content.ContentValues;

importandroid.content.Context;

importandroid.database.Cursor;

importandroid.database.DatabaseErrorHandler;

importandroid.database.sqlite.SQLiteDatabase;

importandroid.database.sqlite.SQLiteOpenHelper;

importandroid.text.TextUtils;

importjava.util.ArrayList;

importjava.util.List;

publicclassDataDBextendsSQLiteOpenHelper {

privateSQLiteDatabase db;

publicDataDB(Context context) {

super(context,"db_test_fts.db",null,1,newDatabaseErrorHandler() {

publicvoidonCorruption(SQLiteDatabase sqLiteDatabase) {

//TODO

}

});

db = getWritableDatabase();

}

publicvoidonCreate(SQLiteDatabase sqLiteDatabase) {

//创建虚拟表

sqLiteDatabase.execSQL("CREATE VIRTUAL TABLE fts_test USING fts4(title, body);");

db = sqLiteDatabase;

//插入数据

bulkInsert(newString[]{"标题1","标题2","标题3"},newString[]{"Java是全世界最好的变成语言","Android是最牛逼的手机系统","Java是Android应用层的主要编程语言"});

}

publicvoidonUpgrade(SQLiteDatabase sqLiteDatabase,inti,inti1) {

}

//插入单条数据

publicvoidinsert(String title, String body) {

ContentValues values =newContentValues();

values.put("title", title);

values.put("body", body);

db.insert("fts_test",null, values);

}

//批量插入数据

publicvoidbulkInsert(String[] titleArray, String[] bodyArray) {

if(titleArray ==null|| bodyArray ==null|| titleArray.length ==0|| titleArray.length != bodyArray.length) {

return;

}

db.beginTransaction();

for(inti =0; i < titleArray.length; i++) {

ContentValues values =newContentValues();

values.put("title", titleArray[i]);

values.put("body", bodyArray[i]);

db.insert("fts_test",null, values);

}

db.setTransactionSuccessful();

db.endTransaction();

}

//查询title字段包含text内容的数据

publicList queryTitle(String text) {

List resultList =null;

Cursor cursor = db.rawQuery("SELECT * FROM fts_test WHERE title MATCH '"+ text +"*';",null);

System.out.println("wenjun cursor title = "+ (cursor ==null?null: cursor.getCount()));

if(cursor !=null&& cursor.getCount() >0) {

resultList =newArrayList<>();

while(cursor.moveToNext()) {

resultList.add(cursor.getString(0));

}

}

returnresultList;

}

//查询body字段包含text内容的数据

publicList queryBody(String text) {

List resultList =null;

Cursor cursor = db.rawQuery("SELECT * FROM fts_test WHERE body MATCH '"+ text +"*';",null);

System.out.println("wenjun cursor body = "+ (cursor ==null?null: cursor.getCount()));

if(cursor !=null&& cursor.getCount() >0) {

resultList =newArrayList<>();

while(cursor.moveToNext()) {

resultList.add(cursor.getString(0));

}

}

returnresultList;

}

//查询全文包含text内容的数据

publicList queryAll(String text) {

List resultList =null;

Cursor cursor = db.rawQuery("SELECT docid, * FROM fts_test WHERE fts_test MATCH '"+ text +"*';",null);

if(cursor !=null&& cursor.getCount() >0) {

resultList =newArrayList<>();

while(cursor.moveToNext()) {

resultList.add(String.valueOf(cursor.getString(0)) +" | "+ cursor.getString(1) +" | "+ cursor.getString(2));

}

}

returnresultList;

}

//获取包含text内容的记录数

publiclonggetCount(String text) {

longresult =0;

String match =";";

if(!TextUtils.isEmpty(text)) {

match =" WHERE fts_test MATCH '"+ text +"*';";

}

Cursor cursor = db.rawQuery("SELECT count(*) FROM fts_test"+ match,null);

if(cursor !=null&& cursor.getCount() >0) {

cursor.moveToFirst();

result = cursor.getLong(0);

}

returnresult;

}

}

结语

全文检索技术的核心是分词算法以及存储的数据结构,目前Sqlite3 FTS主要使用的是B-树的存储方式,其最低搜索性能O[log2N]

在Android客户端中可根据实际的业务场景从分词算法方面来优化。

参考文献:

https://www.sqlite.org/fts3.html

https://www.sqlite.org/fileformat.html#varint_format

http://www.doc88.com/p-3337920383826.html

https://juejin.im/entry/59e6cd266fb9a0451968ab02

https://blog.csdn.net/andanlan/article/details/54237493

http://www.droidsec.cn/特性还是漏洞?滥用-sqlite-分词器/

https://blog.csdn.net/hguisu/article/details/7962350

https://www.cnblogs.com/binyue/archive/2013/10/21/3380750.html

https://raw.githubusercontent.com/wangwang4git/SQLite3-ICU/master/sqlite-amalgamation-3081002/sqlite3.c

https://tartarus.org/martin/PorterStemmer/返回搜狐,查看更多

责任编辑:


http://chatgpt.dhexx.cn/article/fdu53E5S.shtml

相关文章

seg:NLP之正向最大匹配分词

已迁移到我新博客,阅读体验更佳seg:NLP之正向最大匹配分词 完整代码实现放在我的github上:click me 一、任务要求 实现一个基于词典与规则的汉语自动分词系统。 二、技术路线 采用正向最大匹配(FMM)方法对输入的中文语句进行分词&#xff0c;具体的实现可以分为下面几个步骤&am…

Elasticsearch搜索技术实战

elasticsearch下载安装 本篇前述的ES版本是7.14.2&#xff0c;实现了与Mysql的数据同步&#xff0c;ES端的搜索与分词&#xff1b;后来由于和Springcloud&#xff08;spring-data-elasticsearch:3.0.6&#xff09;集成发现版本问题&#xff0c;换成ES5.5.0&#xff0c;所以完整…

Docker技术

在这里插入代码片# Docker 官方文档地址:https://www.docker.com/get-started 中文参考手册:https://docker_practice.gitee.io/zh-cn/ 1.什么是 Docker 1.1 官方定义 最新官网首页 # 1.官方介绍 - We have a complete container solution for you - no matter who you are…

Elasticsearch - 文档分析,IK分词器;文档冲突(十二)

阅读本文前可先参考 Elasticsearch - Elasticsearch详解&#xff1b;安装部署&#xff08;一&#xff09;_MinggeQingchun的博客-CSDN博客 https://blog.csdn.net/MinggeQingchun/article/details/126855747 一、文档分析 文档分析过程如下&#xff1a; 1、将一块文本分成适…

springboot+Elasticsearch实现word,pdf,txt内容抽取并高亮分词全文检索

文章目录 需求 一、环境 二、功能实现 1.搭建环境 2.文件内容识别 三.代码 需求 产品希望我们这边能够实现用户上传PDF,WORD,TXT之内得文本内容&#xff0c;然后用户可以根据附件名称或文件内容模糊查询文件信息&#xff0c;并可以在线查看文件内容 一、环境 项目开发环境&…

使用lucce分词怎么_ElasticSearch 分词器,了解一下

这篇文章主要来介绍下什么是 Analysis &#xff0c;什么是分词器&#xff0c;以及 ElasticSearch 自带的分词器是怎么工作的&#xff0c;最后会介绍下中文分词是怎么做的。 首先来说下什么是 Analysis&#xff1a; 什么是 Analysis&#xff1f; 顾名思义&#xff0c;文本分析就…

自然语言处理 # 中文分词技术 概述

定义 中文分词&#xff08;Chinese Word Segmentation&#xff09;就是将连续的字序列按照一定的规范重新组合成词序列的过程。 Ques:为什么要分词&#xff1f; Ans: 词是最小的能够独立运用的语言单位 Ques:什么是独立运用呢&#xff1f; Ans:它可以解释为“单独做句法成分或…

Python 中 concurrent.futures 模块使用说明

Python 中 concurrent.futures 模块使用说明 转载请注明出处&#xff1a;https://blog.csdn.net/jpch89/article/details/87643972 文章目录 Python 中 concurrent.futures 模块使用说明0. 参考资料1. 概述2. Executor Object 执行器对象3. ThreadPoolExecutor 线程池执行器4.…

【ruoyi】java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ScheduledThreadPoo

前言 ruoyi 4.6.0jdk1.8 错误 11:48:16.879 [http-nio-9031-exec-25] INFO c.r.f.s.r.UserRealm - [doGetAuthenticationInfo,128] - 对用户[admin]进行登录验证..验证未通过{} java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ScheduledThre…

【学习积累】Queue 与 ConcurrentQueue性能测试

在 C# 中&#xff0c;关于队列&#xff08;Queue&#xff09;有两种&#xff0c;一种就是我们普通使用的队列&#xff0c;另一种是线程安全的队列 ConcurrentQueue<T> 。 ConcurrentQueue表示线程安全的先进先出 (FIFO) 集合。https://learn.microsoft.com/zh-cn/dotnet…

Python报错ModuleNotFoundError: No module named ‘concurrent‘

在测试Python的多线程时&#xff0c;根据官方的说法&#xff0c;concurrent.futures在Python3中已经内置了&#xff0c;不需要下载安装&#xff0c;如果是Python2则需要运行pip install futures进行安装。。。 这样导入&#xff0c;两种写法均可 import concurrent.futures #…

go语言工具_Concurrent Map

Concurrent Map 背景 map是平时项目中经常用到的数据类型&#xff0c;但是如果多个协程去读写同一个map时&#xff0c;为了不发生数据错误&#xff0c;经常去将其和锁封装成一个新的map。像以下两种示例。 type LockMap struct { m map[interface{}]interface{} l…

C#线程安全队列ConcurrentQueue

ConcurrentQueue成员函数 入队(EnQueue) 、出队(TryDequeue) 、是否为空(IsEmpty)、获取队列内元素数量(Count)。 void Enqueue(T item) 入队函数&#xff0c;当队列已满时会自动增加队列容量。 bool TryDequeue(T* result) 尝试移除并返回并发队列开头处对象&#xff0c;…

项目优化>C++,concurrentqueue(高性能并发队列)

项目中的数据队列基于轮询和selep的实时性及CUP性能差&#xff0c;需要进行优化&#xff0c;尝试使用concurrentqueue进行优化。网上有一些资料介绍,可供参考。 使用后的个人理解:一个线程安全的queue&#xff0c;并且concurrentqueue的线程安全并不是一味的加锁&#xff0c;它…

ConcurrentMap

ConcurrentMap&#xff0c;它是一个接口&#xff0c;是一个能够支持并发访问的java.util.map集合&#xff1b; ConcurrentHashMap是一个线程安全&#xff0c;并且是一个高效的HashMap。 spring 缓存注解 通过查看源代码发现将数据存在ConcurrentMap中 1 Map并发集合 1.1 Co…

学习线程安全队列ConcurrentQueue

首先,基本使用&#xff1a;入队(EnQueue) 、出队(TryDequeue) 、是否为空(IsEmpty)、获取队列内元素数量(Count)。 一、ConcurrentQueue内部结构: 1.实现原理 众所周知&#xff0c;在普通的非线程安全队列有两种实现方式: 1.使用数组实现的循环队列。 2.使用链表实现的队列…

并发系列(六)-----concurrent的简单介绍

一 简介 concurrent包是jdk1.5引入的重要的包&#xff0c;主要代码由大牛Doug Lea完成。这个包下的一些类如果用好了可以很方便的保证数据在多线程下操作的正确性。就比如说线程共享的i&#xff0c;如果使用concurrent包下的Atomic系列类可以很方便的解决这个问题。这篇文章简单…

python并发之concurrent快速入门

导读&#xff1a;我很笨&#xff0c;但是我很快——计算机之所以计算能力如此出众&#xff0c;不在于其有多智能&#xff0c;而是因为它超快的执行速度&#xff0c;而多核心则可以进一步成倍的提高效率。在python中&#xff0c;concurrent库就是用于完成并发的模块之一。 01 初…

Java 并发工具包(concurrent)详解

目录 一、concurrent并发包 二、ReentrantLock&#xff08;可重入锁&#xff09; 1、锁状态中断与可重入 2、尝试非阻塞地获取锁 3、等待可中断 4、设置公平锁 三、CountDownLatch&#xff08;门栓&#xff09; 四、cyclicBarrier&#xff08;栅栏&#xff09; 五、…

JAVA中split函数的用法

JAVA中split函数的用法 只写经常使用的&#xff0c;并不完整。 1.基本用法&#xff0c;将字符串按照指定字符串进行分割&#xff0c;例如&#xff1a; public class Main {public static void main(String[] args) {String ss "abcabcdefg";String[] split ss.sp…