基于确定有穷自动机(DFA算法)实现敏感词过滤

news2024/12/27 11:38:15

1.DFA算法简介

DFA(Deterministic Finite Automaton) 是一种非递归自动机,也称为确定有穷自动机。它是通过event和当前的state得到nextstate,即event+state=nextstate。

确定:状态以及引起状态转换的事件都是可确定的。

有穷:状态以及引起状态转换的事件的数量都是可穷举的。

对于以下状态转换图:

(S,a) -> U
(S,b) -> V
(U,a) -> Q
(U,b) -> V
(V,a) -> U
(V,b) -> Q
(Q,a) -> Q
(Q,b) -> Q

image-20230601175533650

我们可以将每个文本片段作为状态,例如“匹配关键词”可拆分为“匹”、“匹配”、“匹配关”、“匹配关键”和“匹配关键词”五个文本片段。

image-20230601175948960

过程:

  • 初始状态为空,当触发事件“匹”时转换到状态“匹”;
  • 触发事件“配”,转换到状态“匹配”;
  • 依次类推,直到转换为最后一个状态“匹配关键词”。

再让我们考虑多个关键词的情况,例如“匹配算法”、“匹配关键词”以及“信息抽取”。

image-20230601180036879

可以看到上图的状态图类似树形结构,也正是因为这个结构,使得 DFA 算法在关键词匹配方面要快于关键词迭代方法(for 循环)。

2.Java对DFA算法的实现思路

image-20230601175533650

在Java中实现敏感词过滤的关键就是DFA算法的实现。

我们可以认为,通过S query U、V,通过U query V、P,通过V query U P。通过这样的转变我们可以将状态的转换转变为使用Java集合的查找

如果有以下词为敏感词:日本人日本鬼子

image-20230601180757624

这样我们就将我们的敏感词库构建成了一个类似与一颗一颗的树,这样我们判断一个词是否为敏感词时就大大减少了检索的匹配范围。比如我们要判断日本人,根据第一个字我们就可以确认需要检索的是那棵树,然后再在这棵树中进行检索。

但是如何来判断一个敏感词已经结束了呢?利用标识位来判断。

所以对于这个关键是如何来构建一棵棵这样的敏感词树。下面我以Java中的HashMap为例来实现DFA算法。以日本人,日本鬼子为例,具体过程如下:

  1. 首先获取到根节点HashMap,判断“日”是否存在于根节点当中,如果不存在,则表示该敏感词还不存在。则以“日”为key,创建新的HashMap为value做为根节点。
  2. 如果存在,则表示已经存在含有以“日”开头的敏感词。设置hashMap = hashMap.get(“日”),接着依次匹配“本”、“人”。
  3. 判断该字是否为该词中的最后一个字。若是表示敏感词结束,设置标志位isEnd = 1,否则设置标志位isEnd = 0;
image-20230601233249710

3.Java对DFA算法的实现案例

假如以“日本人”和“日本鬼子”为敏感词,以下为实现过程

image-20230602082834955

image-20230601180757624

代码实现:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class DFAHashMap {
    public void createDFAHashMap(List<String> strings) {
//        1.创建dfaHashMap,此HashMap就表示一个树形结构。
//          指定容量为集合strings的长度,避免dfaHashMap在添加的数据的时候动态扩容
        HashMap<String, Object> dfaHashMap = new HashMap<>(strings.size());
//        2.创建temporaryHashMap,用于装载临时HashMap数据
        HashMap<String, Object> temporaryHashMap = new HashMap<>(strings.size());
//        3.遍历字符串
        for (String string : strings) {
//          3.1对于每个字符串,首个temporaryHashMap就是dfaHashMap,就是树型结构的根节点,
//             即temporaryHashMap首先指向根节点dfaHashMap的内存地址。
            temporaryHashMap = dfaHashMap;
//        4.遍历字符串中的每个字符
            for (int i = 0; i < string.length(); i++) {
//        5.查询在当前temporaryHashMap当中是否存在当前字符
                String word = String.valueOf(string.charAt(i));
                HashMap<String, Object> resultHashMap = (HashMap<String, Object>) temporaryHashMap.get(word);
                if (resultHashMap == null) {
//        6.如果当前dfaHashMap当中不存在当前字符,就以当前字符为key,新建HashMap作为Value
                    resultHashMap = new HashMap<String, Object>();
//          6.1由于temporaryHashMap指向的就是dfaHashMap的内存地址,所以dfaHashMap当中存储了该值
                    temporaryHashMap.put(word, resultHashMap);
                }
//        7.将temporaryHashMap的地址指向下一个HashMap
                temporaryHashMap = resultHashMap;
//        8.判断是否跳过本次循环
//          如果temporaryHashMap里面已经有isEnd,并且为1,说明时树形结构中已经存在的敏感词,就不再设置isEnd
//          如日本和日本鬼子,先设置日本
//          在日本鬼子设置的时候,本对应的map有isEnd=1,如果这时对它覆盖,就会isEnd=0,导致日本这个关键字失效
                if(temporaryHashMap.containsKey("isEnd")&&temporaryHashMap.get("isEnd").equals(1)){
                    continue;
                }
//        8.封装temporaryHashMap
//          8.1判断当前字符是否为字符串的最后一个字符
                if (i == string.length() - 1) {
                    temporaryHashMap.put("isEnd", 1);
                } else {
                    temporaryHashMap.put("isEnd", 0);
                }
            }
        }
        System.out.println(dfaHashMap);
    }
    public static void main(String[] args) {
        List<String> strings = new ArrayList<>();
        strings.add("日本人");
        strings.add("日本鬼子");
        new DFAHashMap().createDFAHashMap(strings);
    }
}

结果如下:

image-20230601200420433

{日=
	{本=
		{人={isEnd=1}, 
         鬼=
         	{子={isEnd=14}, 
         isEnd=0}, 
     isEnd=0}, 
  isEnd=0}}

4.综合实战

4.1敏感词库初始化类

该类的作用主要是读取敏感词文件,并使用DFA算法初始化敏感词库。

  • public HashMap<String, Object> getSensitiveWordHashMap():

    调用readSensitiveWordFile()方法获取到敏感词集合,再调用initSensitiveHashMap()方法使用DFA算法初始化敏感词库。

  • private Set readSensitiveWordFile()

    读取敏感词文件,返回敏感词集合

  • private Map initSensitiveHashMap(Set strings):

    将敏感词集合封装为HashMap<String,Object>类型,初始化敏感词库。

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;

import java.io.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 敏感词库初始化
 *
 * @date 2023/06/02
 */
@Slf4j
public class SensitiveWordInitialize {

    // 字符编码
    private String ENCODING = "UTF-8";

    /**
     * 敏感词库变量
     */
    private HashMap<String, Object> sensitiveWordHashMap = null;

    /**
     * 获取到敏感词库
     *
     * @return {@link HashMap}<{@link String}, {@link Object}>
     * @throws IOException ioexception
     */
    public HashMap<String, Object> getSensitiveWordHashMap() throws IOException {
        log.info("敏感词库初始化");
        Set<String> strings = readSensitiveWordFile();
        System.out.println(strings.size());
        sensitiveWordHashMap = (HashMap<String, Object>) initSensitiveHashMap(strings);
        return sensitiveWordHashMap;
    }

    /**
     * 敏感词文件读取
     *
     * @return {@link Set}<{@link String}>
     */
    private Set<String> readSensitiveWordFile() {
        Set<String> wordSet = null;
        ClassPathResource classPathResource = new ClassPathResource("sensitive_words.txt");
//        1.获取文件字节流
        InputStream inputStream = null;
        InputStreamReader inputStreamReader = null;
        try {
            inputStream = classPathResource.getInputStream();
//        2.实现字节流和字符流之间的转换
            inputStreamReader = new InputStreamReader(inputStream, ENCODING);
            wordSet = new HashSet<>();
//        3.使用缓冲流进行读取
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String txt = null;
            while ((txt = bufferedReader.readLine()) != null) {
                wordSet.add(txt);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (inputStreamReader != null) {
                try {
                    inputStreamReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return wordSet;
    }


    /**
     * 基于DFA算法初始化敏感词库
     *
     * @param strings 字符串
     */
    private Map initSensitiveHashMap(Set<String> strings) {
        sensitiveWordHashMap = new HashMap<>(strings.size());
//        1.创建temporaryHashMap用于存储临时数据
        HashMap<String, Object> temporaryHashMap = new HashMap<>();
//        2.遍历敏感词列表
        for (String string : strings) {
//        3.对于temporaryHashMap,其初始值就是为根节点sensitiveWordHashMap
            temporaryHashMap = sensitiveWordHashMap;
//        4.遍历每个字符
            for (int i = 0; i < string.length(); i++) {
                String word = String.valueOf(string.charAt(i));
//              4.1判断根据点是否存在该字符
                HashMap<String, Object> resultHashMap = (HashMap<String, Object>) temporaryHashMap.get(word);
//              4.2如果为空就创建节点
                if (resultHashMap == null) {
                    resultHashMap = new HashMap<String, Object>();
//              4.3以当前字符为key,new HashMap为value创建节点
                    temporaryHashMap.put(word, resultHashMap);
                }
//        5.temporaryHashMap指向下一个HashMap
                temporaryHashMap = resultHashMap;
//        6.判断是否跳过本次循环
//          如果temporaryHashMap里面已经有isEnd,并且为1,说明时树形结构中已经存在的敏感词,就不再设置isEnd
//          如日本和日本鬼子,先设置日本
//          在日本鬼子设置的时候,本对应的map有isEnd=1,如果这时对它覆盖,就会isEnd=0,导致日本这个关键字失效
                if (temporaryHashMap.containsKey("isEnd") && temporaryHashMap.get("isEnd").equals(1)) {
                    continue;
                }
//        7.封装temporaryHashMap
//          7.1判断当前字符是否为字符串的最后一个字符
                if (i == string.length() - 1) {
                    temporaryHashMap.put("isEnd", 1);
                } else {
                    temporaryHashMap.put("isEnd", 0);
                }
            }
        }
        return sensitiveWordHashMap;
    }
}

4.2敏感词工具类

该类的采用单例模式获取到敏感词库,并对字符串进行敏感词过滤替换。

  • private SensitiveReplaceUtil():

    在构造函数当中调用敏感词库初始化类,获取到敏感词库。

  • public static SensitiveReplaceUtil getInstance():

    采用单例模式,确保该类只有一个实例。

  • public String replaceSensitiveWord(String string, int matchType):

    替换字符串当中的敏感词。首先调用getSensitiveWord()方法获取到当前字符串当中的敏感词集合,并遍历敏感词集合。调用getReplaceString方法根据敏感词长度生成对应的替代词。替换当前敏感词。

  • private String getReplaceString(int length)

    根据敏感词长度生成对应的替换字符串。

  • public Set getSensitiveWord(String string, int matchType):

    获取到敏感词集合。在该方法中根据用户输入的字符串,调用getStringLength()方法获取到敏感词在此字符串当中的索引位置。截取敏感词并添加到敏感词集合中返回。

  • public int getStringLength(String string, int beginIndex, int matchType):

    返回敏感词长度。在该方法中获取到敏感词库,根据敏感词库检查文字中是否包含敏感字符,如果存在,则返回敏感词字符的长度,不存在返回0

import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.*;

/**
 * 敏感词过滤工具类
 *
 * @author Xu huaiang
 * @date 2023/06/02
 */
@Component
public class SensitiveReplaceUtil {
    /**
     * 敏感词过滤器:利用DFA算法  进行敏感词过滤
     */
    private static HashMap<String, Object> sensitiveWordHashMap = null;

    /**
     * 单例
     */
    private static SensitiveReplaceUtil instance = null;

    /**
     * 最小匹配规则,如:敏感词库["中国","中国人"],语句:"我是中国人",匹配结果:我是[中国]人
     */
    public static int minMatchType = 1;
    /**
     * 最大匹配规则,如:敏感词库["中国","中国人"],语句:"我是中国人",匹配结果:我是[中国人]
     */
    public static int maxMatchType = 2;
    /**
     * 敏感词替换词
     */
    public static String replaceChar = "*";

   /**
     * 在构造函数中初始化敏感词库
     *
     * @throws IOException
     */
    private SensitiveReplaceUtil() throws IOException {
        sensitiveWordHashMap = new SensitiveWordInitialize().getSensitiveWordHashMap();
    }
    
    /**
     * 获得单例对象
     *
     * @return {@link SensitiveReplaceUtil}
     * @throws IOException ioexception
     */
    public static SensitiveReplaceUtil getInstance() throws IOException {
        if (instance == null) {
            instance = new SensitiveReplaceUtil();
        }
        return instance;
    }


    /**
     * 替换字符串当中的敏感词
     *
     * @param string    字符串
     * @param matchType 匹配类型
     * @return {@link String}
     */
    public String replaceSensitiveWord(String string, int matchType) {
        String resultString = string;
//        1.获取到当前字符串中的敏感词集合
        Set<String> sensitiveWord = getSensitiveWord(string, matchType);
//        2.迭代遍历敏感词集合
        Iterator<String> iterator = sensitiveWord.iterator();
        while (iterator.hasNext()) {
//            2.1获取到敏感词
            String word = iterator.next();
//            2.2根据敏感词长度创建替代字符串
            String replaceString = getReplaceString(word.length());
//            2.3替换字符串
            resultString = resultString.replaceAll(word, replaceString);
        }
        return resultString;
    }

    /**
     * 根据敏感词长度创建替代字符串
     *
     * @param length 长度
     * @return {@link String}
     */
    private String getReplaceString(int length) {
        StringBuilder replaceString = new StringBuilder();
//        根据敏感词长度创建替代字符串
        for (int i = 0; i < length; i++) {
            replaceString.append(replaceChar);
        }
        return replaceString.toString();
    }

    /**
     * 获取到字符串中的敏感词集合
     *
     * @param string    字符串
     * @param matchType 匹配类型
     * @return {@link Set}<{@link String}>
     */
    public Set<String> getSensitiveWord(String string, int matchType) {
        Set<String> set = new HashSet<>();
//        1.遍历字符串中的每一个字符
        for (int i = 0; i < string.length(); i++) {
            int length = getStringLength(string, i, matchType);
//        2.如果length大于0表示存在敏感词,将敏感词添加到集合中
            if (length > 0) {
                set.add(string.substring(i, i + length));
            }
        }
        return set;
    }


    /**
     * 检查文字中是否包含敏感字符,检查规则如下:
     * 如果存在,则返回敏感词字符的长度,不存在返回0
     *
     * @param string     字符串
     * @param beginIndex 开始下标
     * @param matchType  匹配类型
     * @return int
     */
    public int getStringLength(String string, int beginIndex, int matchType) {
//        1.当前敏感词长度,用作累加
        int nowLength = 0;
//        2.最终敏感词长度
        int resultLength = 0;
//        3.获取到敏感词库
        HashMap<String, Object> temporaryHashMap = sensitiveWordHashMap;
//        4.遍历字符串
        for (int i = beginIndex; i < string.length(); i++) {
//        5.判断当前字符是否为敏感词库中的首个字母
            String word = String.valueOf(string.charAt(i));
            temporaryHashMap = (HashMap<String, Object>) temporaryHashMap.get(word);
//            5.1如果为空表示当前字符并不为敏感词
            if (temporaryHashMap == null) {
                break;
            } else {
                nowLength++;
//            5.2判断是否为最后一个敏感词字符
                if (temporaryHashMap.get("isEnd").equals(1)) {
                    resultLength = nowLength;
//            5.3判断匹配原则,如果为2表示最大匹配原则,继续匹配,为1结束匹配
                    if (matchType == minMatchType) {
                        break;
                    }
                }
            }
        }
        return resultLength;
    }
}

4.3测试

在Controller层创建请求映射,用来模拟用户查询请求。

import com.vector.score.utils.SensitiveReplaceUtil;
import lombok.extern.slf4j.Slf4j;
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 java.io.IOException;

@Slf4j
@RestController
@RequestMapping("/sensitive")
public class SensitiveTestController {

    @GetMapping("/test")
    public void test(@RequestParam("string") String string) throws IOException {
        String word = SensitiveReplaceUtil.getInstance().replaceSensitiveWord(string, 2);
        log.info("替换前的字符串为:" + string);
        log.info("替换后的字符串为:" + word);
    }
}

image-20230602191447340

查看控制台打印:

image-20230602191747193
参考博客1
参考博客2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/602953.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

EBU6304 Software Engineering 知识点总结_4 analysis, design, implementation, testing

analysis 仅仅从用户的需求来看得到的消息不全面&#xff0c;还需要分析。用户可能认为你明白了&#xff0c;或者他考虑不全面&#xff0c;觉得一些地方是不需要的。 因此我们需要分析来 Refining requirements。 gather requirements-analyse in real world context-develo…

(字符串 ) 剑指 Offer 58 - II. 左旋转字符串 ——【Leetcode每日一题】

❓剑指 Offer 58 - II. 左旋转字符串 难度&#xff1a;简单 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如&#xff0c;输入字符串"abcdefg"和数字2&#xff0c;该函数将返回左旋转两位得到的…

Codeforces Round 875 (Div. 2)

Problem - D - Codeforces 思路&#xff1a; 注意到bibj<2*n&#xff0c;所以ai*aj<2*n&#xff0c;即我们实际只需要枚举个a的匹配即可为了不重不漏&#xff0c;我们可以枚举x从1到&#xff0c;寻找所有与x匹配且大于等于x的[a,b]对这样复杂度就是 #include <bits…

OpenCV笔记整理【人脸检测之Harr级联分类器dlib库】

1. 级联分类器&#xff1a; OpenCV提供的级联分类器有Harr、HOG、LBP这3种&#xff0c;这些分类器以XML文件保存&#xff0c;这里主要演示Harr检测人脸&#xff08;OpenCV提供的分类器不仅限于检测人脸&#xff0c;还包括下表特征检测&#xff0c;当然OpenCV还支持训练自己的级…

Vim学习笔记【Ch02】

Vim学习笔记 系列笔记链接Ch02 Buffers, Windows, TabsBuffers什么是buffer查看所有bufferbuffer之间的切换删除buffer退出所有窗口 Windows窗口的创建窗口切换快捷键其他快捷键 Tabs什么是tabtab相关命令 window和buffer结合的3D移动小结 系列笔记链接 Ch00&#xff0c;Ch01 …

python介绍——入门

前言 Python 是一种面向对象的解释型计算机程序设计语言&#xff0c;它继承了传统编译语言的强大性和通用性&#xff0c;同时也借鉴了脚本语言和解释语言的易用性。今天我就来给大家简单介绍一下python&#xff1a; 一、python的起源 1989年的圣诞节期间&#xff0c;吉多▪范…

Redis底层学习(二)—存储类型-String篇

这里写目录标题 应用场景底层结构知识普及 应用场景 服务器命令&#xff1a; 1.单值缓存 存储key,value &#xff1a;SET key value2.对象缓存 存储key,value :SET key value&#xff08;json 格式数据&#xff09; 3.分布式锁 底层结构 我们可以通过命令查看 value…

C++ 学习 ::【基础篇:14】:C++ 类的基本成员函数:析构函数的作用 及 自定义析构函数情形

本系列 C 相关文章 仅为笔者学习笔记记录&#xff0c;用自己的理解记录学习&#xff01;C 学习系列将分为三个阶段&#xff1a;基础篇、STL 篇、高阶数据结构与算法篇&#xff0c;相关重点内容如下&#xff1a; 基础篇&#xff1a;类与对象&#xff08;涉及C的三大特性等&#…

scratch找食物 中国电子学会图形化编程 少儿编程 scratch编程等级考试一级真题和答案解析2023年5月

目录 scratch找食物 一、题目要求 1、准备工作 2、功能实现 二、案例分析

全志V3S嵌入式驱动开发(多按键输入驱动)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们说过&#xff0c;荔枝派的开发板上面&#xff0c;有4个按键本身不是通过gpio连接到soc上面的。它是通过ad的方法&#xff0c;连接到主芯片…

SpringCloud GateWay-Filter学习

3 Filter/过滤器 文章目录 3 Filter/过滤器1 GatewayFilter 使用 -- 路由过滤器2 GatewayFilter 使用 -- 自定义过滤器 路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应Spring Cloud Gateway 内置了多种路由过滤器&#xff0c;他们都由GatewayFilter的工厂类来产生 1 Gat…

华为OD机试真题B卷 Java 实现【IPv4地址转换成整数】,附详细解题思路

一、题目描述 存在一种虚拟 IPv4 地址&#xff0c;由4小节组成&#xff0c;每节的范围为0~255&#xff0c;以#号间隔&#xff0c; 虚拟 IPv4 地址可以转换为一个32位的整数&#xff0c;例如&#xff1a; 128#0#255#255&#xff0c;转换为32位整数的结果为2147549183&#xff0…

以技术实践赋能开源安全|2023开放原子全球开源峰会开源安全技术与实践分论坛即将启幕

作为数字化转型时代的重要技术和协作模式&#xff0c;开源软件在各行各业得到广泛应用&#xff0c;由此也引发了诸多与安全相关的问题。6月12日&#xff0c;2023开放原子全球开源峰会“开源安全技术与实践”分论坛将在北京经开区北人亦创国际会展中心举行。 本次分论坛由开放原…

为什么说 Go 语言字符串是不可变的?

原文链接&#xff1a; 为什么说 Go 语言字符串是不可变的&#xff1f; 最近有读者留言说&#xff0c;平时在写代码的过程中&#xff0c;是会对字符串进行修改的&#xff0c;但网上都说 Go 语言字符串是不可变的&#xff0c;这是为什么呢&#xff1f; 这个问题本身并不困难&am…

SAP-QM-物料主数据-质量管理视图字段解析

过账到质检库存&#xff1a;要勾选&#xff0c;否则收货后库存不进入质检库存HU检验&#xff1a;收货到启用HU管理的库位时产生检验批&#xff0c;例如某个成品物料是收货到C002库位&#xff0c;该库位启用了HU管理&#xff0c;那么此处要勾选。但是如果勾选了&#xff0c;却收…

30天学会vue.js?|vue.js 3 移动应用开发实战 阅读笔记

最近又在折腾vuejs, 计划用30天的时间来掌握这个前端语言。 大概用了一周时间看完这本书。 这本书需要有编程基础的同学阅读。如果从零开始学前端的话&#xff0c;个人不建议&#xff0c;书本内容跳跃性很大&#xff0c;甚至个人觉得有点凌乱。PS&#xff1a;阅读此书一定要配…

黑马Redis视频教程实战篇(五)

目录 一、达人探店 1.1、发布探店笔记 1.2、查看探店笔记 1.3、点赞功能 1.4、点赞排行榜 二、好友关注 2.1、关注和取消关注 2.2、共同关注 2.3、Feed流实现方案 2.4、推送到粉丝收件箱 2.4、实现分页查询收邮箱 一、达人探店 1.1、发布探店笔记 发布探店笔记 探…

自定义组件和样式学习

一、使用组件3步 例如&#xff1a;APP.vue中使用另外两个组件Left.vue,Right.vue &#xff08;3个页面&#xff09; 1.在APP.vue中用import *** from **** 导入Left.vue、Right.vue页面 2.在APP.vue的js中和data同级注册&#xff0c;components{Left,Rirght} 3.注册完后可在APP…

JAVA内存深度分析报告

文章目录 理论部分&#xff1a;1.Heap Memory&#xff08;堆内存&#xff09;2.Non-heap Memory&#xff08;堆外内存&#xff09;3.Direct Memory&#xff08;直接内存&#xff09; 实验部分&#xff1a;1.Platform MXBeans API 监控快照2.MetaSpace 快照:3.Native Memory 快照…

线程池的实现原理

线程池的实现原理 所谓线程池&#xff0c;通俗的理解就是有一个池子&#xff0c;里面存放着已经创建好的线程&#xff0c;当有任务提交给线程池执行时&#xff0c;池子中的某个线程会主动执行该任务。如果池子中的线程数量不够应付数量众多的任务时&#xff0c;则需要自动扩充…