Hippo4j线程池实现技术

文章目录

  • 🔊博主介绍
  • 🥤本文内容
    • 部署
    • 运行模式
    • 集成
    • 线程池监控配置
    • 参数默认配置
  • 📢文章总结
  • 📥博主目标

🔊博主介绍

🌟我是廖志伟,一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作者、产品软文专业写手、技术文章评审老师、问卷调查设计师、个人社区创始人、开源项目贡献者。🌎跑过十五公里、🚀徒步爬过衡山、🔥有过三个月减肥20斤的经历、是个喜欢躺平的狠人。

📕拥有多年一线研发和团队管理经验,研究过主流框架的底层源码(Spring、SpringBoot、Spring MVC、SpringCould、Mybatis、Dubbo、Zookeeper),消息中间件底层架构原理(RabbitMQ、RockerMQ、Kafka)、Redis缓存、MySQL关系型数据库、 ElasticSearch全文搜索、MongoDB非关系型数据库、Apache ShardingSphere分库分表读写分离、设计模式、领域驱动DDD、Kubernetes容器编排等。

📙有过从0到1的项目高并发项目开发与管理经验,对JVM调优、MySQL调优、Redis调优 、ElasticSearch调优、消息中间件调优、系统架构调优都有着比较全面的实战经验。

📘有过云端搭建服务器环境,自动化部署CI/CD,弹性伸缩扩容服务器(最高200台),了解过秒级部署(阿里云的ACK和华为云的云容器引擎CCE)流程,能独立开发和部署整个后端服务,有过分库分表的实战经验。

🎥经过多年在CSDN创作上千篇文章的经验积累,我已经拥有了不错的写作技巧,与清华大学出版社签下了四本书籍的合约,并将陆续在明年出版。这些书籍包括了基础篇、进阶篇、架构篇的📌《Java项目实战—深入理解大型互联网企业通用技术》📌,以及📚《解密程序员的思维密码–沟通、演讲、思考的实践》📚。具体出版计划会根据实际情况进行调整,希望各位读者朋友能够多多支持!


文章目录

  • 🔊博主介绍
  • 🥤本文内容
    • 部署
    • 运行模式
    • 集成
    • 线程池监控配置
    • 参数默认配置
  • 📢文章总结
  • 📥博主目标

🌾阅读前,快速浏览目录和章节概览可帮助了解文章结构、内容和作者的重点。了解自己希望从中获得什么样的知识或经验是非常重要的。建议在阅读时做笔记、思考问题、自我提问,以加深理解和吸收知识。

💡在这个美好的时刻,本人不再啰嗦废话,现在毫不拖延地进入文章所要讨论的主题。接下来,我将为大家呈现正文内容。

🥤本文内容

CSDN

部署

使用 Docker 运行服务端,默认使用内置 H2 数据库,数据持久化到 Docker 容器存储卷中。

docker run -d -p 6691:6691 --name hippo4j-server \
-e DATASOURCE_MODE=mysql \
-e DATASOURCE_HOST=192.168.3.200 \
-e DATASOURCE_PORT=3306 \
-e DATASOURCE_DB=hippo4j_manager \
-e DATASOURCE_USERNAME=root \
-e DATASOURCE_PASSWORD=root \
hippo4j/hippo4j-server

访问 Server 控制台,路径 http://hadoop3:6691/index.html,默认用户名密码:admin / 123456
在这里插入图片描述

运行模式

Hippo4j 分为两种使用模式:轻量级依赖配置中心以及无中间件依赖版本。
在这里插入图片描述
Hippo4jConfig系统:它提供了极具可行性且灵活的动态线程池管理方案。利用了Nacos、Apollo、Zookeeper、ETCD、Polaris和Consul等多元化的第三方配置中心这些特性,可根据用户需求完成线程池参数的实时调整与更新,从而实现高度智能化的线程池管理功能。此外,该系统还具备实时预警及监控等独特功能,使得整个系统的稳定性得以提高并大幅提升表现效果。

Hippo4jServer服务器:在此基础上进行扩展,并采取了无需借助任何中介软件的全新发布方式,大大降低了系统依赖成本。其主要工作原理是由用户通过直观易懂的Web界面去直接操作线程池的建立、变更以及状态的浏览等任务,由此最大限度地简化了操作流程,减轻了用户负担。虽然Hippo4jServer在各项功能上都远超过Hippo4jConfig,但是在保持稳定性的同时,复杂度也相应有所增加。这就需要在服务器端额外安装一款Java程序以便运行,并且还依赖MySQL数据库作为数据存储设施。

集成

<dependency><groupId>cn.hippo4j</groupId><artifactId>hippo4j-config-spring-boot-starter</artifactId><version>1.5.0</version>
</dependency>

请在应用程序启动类中引入注解@EnablesDynamicThreadPool以实现动态线程池功能。

@SpringBootApplication
@EnableDynamicThreadPool
public class ExampleApplication {public static void main(String[] args) {SpringApplication.run(ExampleApplication.class, args);}
}

请参照示例项目hippo4j-config-nacos-spring-boot-starter-example进行配置调整,具体步骤包括:
1)设定Nacos服务的URL;
2)在Nacos所关联的空间和分组内创建名为hippo4j-nacos.properties的配置文件;
3)将原先在bootstrap.properties文件中的相关配置参数迁移至上述新创配置文件之中。

spring.dynamic.thread-pool.enable=true  # 启用动态线程池
spring.dynamic.thread-pool.banner=true  # 启用线程池横幅
spring.dynamic.thread-pool.check-state-interval=5  # 线程池状态检查间隔(秒)
spring.dynamic.thread-pool.monitor.enable=true  # 启用线程池监控
spring.dynamic.thread-pool.monitor.collect-types=micrometer  # 监控数据收集类型
spring.dynamic.thread-pool.monitor.thread-pool-types=dynamic,web  # 监控的线程池类型
spring.dynamic.thread-pool.monitor.initial-delay=10000  # 监控延迟启动时间(毫秒)
spring.dynamic.thread-pool.monitor.collect-interval=5000  # 监控数据采集间隔(毫秒)
spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT  # 通知平台:微信
spring.dynamic.thread-pool.notify-platforms[0].token=ac0426a5-c712-474c-9bff-72b8b8f5caff  # 微信通知的令牌
spring.dynamic.thread-pool.notify-platforms[1].platform=DING  # 通知平台:钉钉
spring.dynamic.thread-pool.notify-platforms[1].token=56417ebba6a27ca352f0de77a2ae9da66d01f39610b5ee8a6033c60ef9071c55  # 钉钉通知的令牌
spring.dynamic.thread-pool.notify-platforms[2].platform=LARK  # 通知平台:飞书
spring.dynamic.thread-pool.notify-platforms[2].token=2cbf2808-3839-4c26-a04d-fd201dd51f9e  # 飞书通知的令牌
spring.dynamic.thread-pool.executors[0].thread-pool-id=message-consume  # 线程池ID:消息消费
spring.dynamic.thread-pool.executors[0].thread-name-prefix=message-consume  # 线程名前缀:消息消费
spring.dynamic.thread-pool.executors[0].core-pool-size=4  # 核心线程数
spring.dynamic.thread-pool.executors[0].maximum-pool-size=6  # 最大线程数
spring.dynamic.thread-pool.executors[0].queue-capacity=512  # 队列容量
spring.dynamic.thread-pool.executors[0].blocking-queue=ResizableCapacityLinkedBlockingQueue  # 阻塞队列类型
spring.dynamic.thread-pool.executors[0].execute-time-out=800  # 任务执行超时时间(毫秒)
spring.dynamic.thread-pool.executors[0].rejected-handler=AbortPolicy  # 拒绝策略
spring.dynamic.thread-pool.executors[0].keep-alive-time=6691  # 空闲线程存活时间(毫秒)
spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out=true  # 是否允许核心线程超时销毁
spring.dynamic.thread-pool.executors[0].alarm=true  # 是否启用告警
spring.dynamic.thread-pool.executors[0].active-alarm=80  # 活跃线程告警阈值(百分比)
spring.dynamic.thread-pool.executors[0].capacity-alarm=80  # 队列容量告警阈值(百分比)
spring.dynamic.thread-pool.executors[0].notify.interval=8  # 告警通知间隔(秒)
spring.dynamic.thread-pool.executors[0].notify.receives=chen.ma  # 告警通知接收人
spring.dynamic.thread-pool.executors[1].thread-pool-id=message-produce  # 线程池ID:消息生产
spring.dynamic.thread-pool.executors[1].thread-name-prefix=message-produce  # 线程名前缀:消息生产
spring.dynamic.thread-pool.executors[1].core-pool-size=2  # 核心线程数
spring.dynamic.thread-pool.executors[1].maximum-pool-size=4  # 最大线程数
spring.dynamic.thread-pool.executors[1].queue-capacity=1024  # 队列容量
spring.dynamic.thread-pool.executors[1].blocking-queue=ResizableCapacityLinkedBlockingQueue  # 阻塞队列类型
spring.dynamic.thread-pool.executors[1].execute-time-out=800  # 任务执行超时时间(毫秒)
spring.dynamic.thread-pool.executors[1].rejected-handler=AbortPolicy  # 拒绝策略
spring.dynamic.thread-pool.executors[1].keep-alive-time=6691  # 空闲线程存活时间(毫秒)
spring.dynamic.thread-pool.executors[1].allow-core-thread-time-out=true  # 是否允许核心线程超时销毁
spring.dynamic.thread-pool.executors[1].alarm=true  # 是否启用告警
spring.dynamic.thread-pool.executors[1].active-alarm=80  # 活跃线程告警阈值(百分比)
spring.dynamic.thread-pool.executors[1].capacity-alarm=80  # 队列容量告警阈值(百分比)
spring.dynamic.thread-pool.executors[1].notify.interval=8  # 告警通知间隔(秒)
spring.dynamic.thread-pool.executors[1].notify.receives=chen.ma  # 告警通知接收人

在这里插入图片描述
如果是yaml文件,SpringBoot 应用配置文件添加::

server:port: 8090servlet:context-path: /example
spring:profiles:active: devdynamic:thread-pool:# 是否开启动态线程池enable: true# 是否打印 bannerbanner: true# 是否开启线程池数据采集,对接 MicrometerESLog 等collect: true# 检查线程池状态,是否达到报警条件,单位毫秒check-state-interval: 3000# 通知报警平台,请替换为自己创建的群机器人notify-platforms:- platform: 'WECHAT'token: xxx- platform: 'DING'token: xxxsecret: xxx  # 加签专属- platform: 'LARK'token: xxx# NacosApolloZookeeperETCDPolarisConsul 任选其一nacos:data-id: xxxgroup: xxxapollo:namespace: xxxx# 配置中心文件格式config-file-type: yml# 支持 tomcat、undertow、jetty 三种容器线程池web:core-pool-size: 100maximum-pool-size: 200keep-alive-time: 1000# 全局通知配置-是否报警alarm: true# 活跃度报警阈值;假设线程池最大线程数 10,当线程数达到 8 发起报警active-alarm: 80# 容量报警阈值;假设阻塞队列容量 100,当容量达到 80 发起报警capacity-alarm: 80# 报警间隔,同一线程池下同一报警纬度,在 interval 时间内只会报警一次,单位秒alarm-interval: 8# 企业微信填写用户 ID(填写其它将无法达到 @ 效果)、钉钉填手机号、飞书填 ou_ 开头唯一 IDreceives: xxx# 动态线程池列表executors:- thread-pool-id: 'message-consume'# 核心线程数core-pool-size: 1# 最大线程数maximum-pool-size: 1# 阻塞队列名称,参考 BlockingQueueTypeEnum,支持 SPIblocking-queue: 'LinkedBlockingQueue'# 阻塞队列大小queue-capacity: 1# 执行超时时间,超过此时间发起报警,单位毫秒execute-time-out: 1000# 拒绝策略名称,参考 RejectedPolicyTypeEnum,支持 SPIrejected-handler: 'AbortPolicy'# 线程存活时间,单位秒keep-alive-time: 1024# 是否允许核心线程超时allow-core-thread-time-out: true# 线程工厂名称前缀thread-name-prefix: 'message-consume'# 是否报警alarm: true# 活跃度报警阈值;假设线程池最大线程数 10,当线程数达到 8 发起报警active-alarm: 80# 容量报警阈值;假设阻塞队列容量 100,当容量达到 80 发起报警capacity-alarm: 80# 通知配置,线程池中通知配置如果存在,则会覆盖全局通知配置notify:# 报警间隔,同一线程池下同一报警纬度,在 interval 时间内只会报警一次,单位分钟interval: 8# 企业微信填写用户 ID(填写其它将无法达到 @ 效果)、钉钉填手机号、飞书填 ou_ 开头唯一 IDreceives: xxx- thread-pool-id: 'message-produce'core-pool-size: 1maximum-pool-size: 1queue-capacity: 1execute-time-out: 1000blocking-queue: 'LinkedBlockingQueue'rejected-handler: 'AbortPolicy'keep-alive-time: 1024allow-core-thread-time-out: truethread-name-prefix: 'message-consume'alarm: trueactive-alarm: 80capacity-alarm: 80notify:interval: 8receives: xxx

在启动Hippo4j-Config-Nacos-Spring-Boot-Starter-Example工程的 ConfigNacosExampleApplication时,我们需要对Nacos配置中的hippo4j-nacos.properties文件进行一定的修改操作。如此一来,将在控制台上观察到日志输出中包含了有关线程池信息的变动信息。

根据ThreadPoolExecutor的特性,我们必须增加一个新的线程池配置类,并同时使用@DynamicThreadPool注解加以标识。其中,“threadPoolId"字段代表了服务器端所创建的线程池ID。这也是先前在配置文件中设定的参数值,即"spring.dynamic.thread-pool.executors[0].thread-pool-id=message-consume”。

个性化定制方面,Hippo4j-Config主要依赖于配置中心实现线程池配置的动态更改。然而,现阶段在这种模式下存在着一些不足之处,例如:当配置文件发生改变时,会导致所有客户端为了适应变更而重新加载数据。因此,我们希望Hippo4j-Config能够具备如同Hippo4j-Server那样,支持客户端集群个性化配置的能力,以便我们能针对单一客户端进行独立的配置变更调整。

ThreadPoolExecutor 适配
添加线程池配置类,通过 @DynamicThreadPool 注解修饰。threadPoolId 为服务端创建的线程池 ID。

import cn.hippo4j.core.executor.DynamicThreadPool;
import cn.hippo4j.core.executor.support.ThreadPoolBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.ThreadPoolExecutor;@Configuration
public class ThreadPoolConfig {@Bean@DynamicThreadPoolpublic ThreadPoolExecutor messageConsumeDynamicExecutor() {String threadPoolId = "message-consume";ThreadPoolExecutor messageConsumeDynamicExecutor = ThreadPoolBuilder.builder().threadFactory(threadPoolId).threadPoolId(threadPoolId).dynamicPool().build();return messageConsumeDynamicExecutor;}@Bean@DynamicThreadPoolpublic ThreadPoolExecutor messageProduceDynamicExecutor() {String threadPoolId = "message-produce";ThreadPoolExecutor messageProduceDynamicExecutor = ThreadPoolBuilder.builder().threadFactory(threadPoolId).threadPoolId(threadPoolId).dynamicPool().build();return messageProduceDynamicExecutor;}}

通过 ThreadPoolBuilder 构建动态线程池,只有 threadFactory、threadPoolId 为必填项,其它参数会从配置中心拉取。

项目中使用上述定义的动态线程池,如下所示:

@Resource
private ThreadPoolExecutor messageConsumeDynamicExecutor;messageConsumeDynamicExecutor.execute(() -> xxx);@Resource
private ThreadPoolExecutor messageProduceDynamicExecutor;messageProduceDynamicExecutor.execute(() -> xxx);

线程池监控配置

监控前置条件:需要先完成 hippo4j-config 的 接入工作。

接下来引入 SpringBoot Actuator。Spring 2.x 一般都有版本指定,所以这里不用写版本号。

<dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

添加动态线程池监控相关配置:

management:metrics:export:prometheus:enabled: trueserver:port: 29999 # 可选配置,如果不配置该 port,直接使用 ${server.port}endpoints:web:exposure:include: '*' # 测试使用,开启了所有端点,生产环境不建议 *
spring:dynamic:thread-pool:monitor:enable: true # 是否开启采集线程池运行时数据collect-interval: 5000 # 采集线程池运行数据频率collect-types: micrometer # 采集线程池运行数据的类型。eg:log、micrometer。多个可以同时使用,默认 micrometerinitial-delay: 10000 # 项目启动后延迟多久进行采集thread-pool-types: dynamic # 采集线程池的类型。eg:dynamic、web、adapter。可任意配置,默认 dynamic

项目启动,访问 http://localhost:29999/actuator/prometheus 出现 dynamic_thread_pool_ 前缀的指标,即为成功。
在这里插入图片描述
配置 Prometheus
通过 Docker 启动 Prometheus 服务。

docker run -d -p 9090:9090 --name prometheus prom/prometheus

添加 Prometheus 抽取数据任务。
进入 prometheus 容器内部,编辑 prometheus 配置文件

docker exec -it prometheus /bin/sh
vi /etc/prometheus/prometheus.yml

scrape_configs 节点下新添加一个 job,如果 Prometheus 是 Docker 方式部署,{scrape_configs.static_configs.targets} 需要写本机的 IP。

scrape_configs:- job_name: 'dynamic-thread-pool-job'scrape_interval: 5smetrics_path: '/actuator/prometheus'static_configs:- targets: [ '127.0.0.1:29999' ]

配置成功后 exit 退出容器,并进行 Prometheus 容器重启 docker restart prometheus。

访问 Prometheus 控制台 http://localhost:9090/graph 路径,能够展示相关指标即为配置成功。
在这里插入图片描述配置 Grafana

docker run -d -p 3000:3000 --name=grafana grafana/grafana

访问 Grafana 地址,http://localhost:3000 用户名密码:admin

Grafana 访问 http://localhost:3000/datasources 导入 Prometheus 数据源。

在这里插入图片描述
如果 Prometheus 为 Docker 方式部署,HTTP URL 需要为本地 IP,比如:http://192.168.1.5:9090

参数默认配置

项目中线程池一多,配置文件中配置就显得很臃肿。为此 hippo4j-config 开发出了动态线程池默认配置。

spring:dynamic:thread-pool:default-executor:core-pool-size: 4maximum-pool-size: 6blocking-queue: ResizableCapacityLinkedBlockingQueuequeue-capacity: 1024execute-time-out: 1000keep-alive-time: 9999rejected-handler: AbortPolicyactive-alarm: 90capacity-alarm: 85alarm: trueallow-core-thread-time-out: truenotify:interval: 5receives: chen.maexecutors:- thread-pool-id: message-produce- thread-pool-id: message-consumecore-pool-size: 80maximum-pool-size: 100execute-time-out: 1000notify:interval: 6receives: chen.ma

CSDN

📢文章总结

对本篇文章进行总结:

🔔以上就是今天要讲的内容,阅读结束后,反思和总结所学内容,并尝试应用到现实中,有助于深化理解和应用知识。与朋友或同事分享所读内容,讨论细节并获得反馈,也有助于加深对知识的理解和吸收。

以梦为马,不负韶华

🔔如果您需要转载或者搬运这篇文章的话,非常欢迎您私信我哦~

🚀🎉希望各位读者大大多多支持用心写文章的博主,现在时代变了,🚀🎉 信息爆炸,酒香也怕巷子深🔥,博主真的需要大家的帮助才能在这片海洋中继续发光发热🎨,所以,🏃💨赶紧动动你的小手,点波关注❤️,点波赞👍,点波收藏⭐,甚至点波评论✍️,都是对博主最好的支持和鼓励!

  • 💂 博客主页: 我是廖志伟
  • 👉开源项目:java_wxid
  • 🌥 哔哩哔哩:我是廖志伟
  • 🎏个人社区:幕后大佬
  • 🔖个人微信号SeniorRD
  • 🎉微信号二维码SeniorRD

📥博主目标

探寻内心世界,博主分享人生感悟与未来目标

  • 🍋程序开发这条路不能停,停下来容易被淘汰掉,吃不了自律的苦,就要受平庸的罪,持续的能力才能带来持续的自信。我本是一个很普通的程序员,放在人堆里,除了与生俱来的盛世美颜,就剩180的大高个了,就是我这样的一个人,默默写博文也有好多年了。
  • 📺有句老话说的好,牛逼之前都是傻逼式的坚持,希望自己可以通过大量的作品、时间的积累、个人魅力、运气、时机,可以打造属于自己的技术影响力。
  • 💥内心起伏不定,我时而激动,时而沉思。我希望自己能成为一个综合性人才,具备技术、业务和管理方面的精湛技能。我想成为产品架构路线的总设计师,团队的指挥者,技术团队的中流砥柱,企业战略和资本规划的实战专家。
  • 🎉这个目标的实现需要不懈的努力和持续的成长,但我必须努力追求。因为我知道,只有成为这样的人才,我才能在职业生涯中不断前进并为企业的发展带来真正的价值。在这个不断变化的时代,我们必须随时准备好迎接挑战,不断学习和探索新的领域,才能不断地向前推进。我坚信,只要我不断努力,我一定会达到自己的目标。

🔔有需要对自己进行综合性评估,进行职业方向规划,我可以让技术大牛帮你模拟面试、针对性的指导、传授面试技巧、简历优化、进行技术问题答疑等服务。

可访问:https://java_wxid.gitee.io/tojson/

开发人员简历优化、面试突击指导、技术问题解答

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

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

相关文章

力扣热题100_链表_142_环形链表 II

文章目录 题目链接解题思路解题代码 题目链接 142. 环形链表 II 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中…

2024.2.14力扣每日一题——二叉树的层序遍历

2024.2.14 题目来源我的题解方法一 递归实现&#xff08;前序遍历记录深度&#xff09;方法二 非递归实现&#xff08;队列&#xff09; 题目来源 力扣每日一题&#xff1b;题序&#xff1a;102 我的题解 方法一 递归实现&#xff08;前序遍历记录深度&#xff09; 在递归遍…

【Spring】之AOP详解

AOP 什么是AOP&#xff1f; AOP&#xff1a;Aspect Oriented Programming&#xff0c;面向切面编程。 切面指的是某一类特定问题&#xff0c;因此面向切面编程也可以理解为面向特定方法编程。例如&#xff0c;在任何一个系统中&#xff0c;总有一些页面不是用户可以随便访问…

部分背包问题

题源看着是背包&#xff0c;其实是贪心 题目描述 阿里巴巴走进了装满宝藏的藏宝洞。藏宝洞里面有 (N≤100) 堆金币&#xff0c;第 i 堆金币的总重量和总价值分别是mi​,vi​(1≤mi​,vi​≤100)。阿里巴巴有一个承重量为T(T≤1000) 的背包&#xff0c;但并不一定有办法将全部的…

Matlab|配电网三相不平衡潮流计算【隐式Zbus高斯法】【可设定变压器数量、位置、绕组方式】

目录 主要内容 部分代码 结果一览 1.以33节点为例 2.以12节点系统为例 下载链接 主要内容 该模型基于隐式Zbus高斯法实现对配电网的三相不平衡潮流计算&#xff0c;通过选项可实现【不含变压器】和【含变压器】两种方式下的潮流计算&#xff0c;并且通过参数设置…

题目:学习gotoxy()与clrscr()函数

题目&#xff1a;学习gotoxy()与clrscr()函数    There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog content is all parallel goods. Those who are worried about being cheated …

游戏引擎中的声音系统

一、声音基础 1.1 音量 声音振幅的大小 压强p&#xff1a;由声音引起的与环境大气压的局部偏差 1.2 音调 1.3 音色 1.4 降噪 1.5 人的听觉范围 1.6 电子音乐 将自然界中连续的音乐转换成离散的信号记录到内存中 采样 - 量化 - 编码 香农定理&#xff1a;采样频率是信…

如何查询网站是否被搜索引擎收录

怎么看网站有没有被百度收录 对于网站所有者来说&#xff0c;了解自己的网站是否被百度搜索引擎收录是非常重要的。只有被收录&#xff0c;网站才能在百度搜索结果中展现&#xff0c;从而获取流量和曝光。下面介绍几种方法&#xff0c;让您快速了解自己的网站是否被百度收录。…

SpringBoot+uniApp宠物领养小程序系统 附带详细运行指导视频

文章目录 一、项目演示二、项目介绍三、运行截图四、主要代码1.保存宠物信息代码2.提交订单信息代码3.查询评论信息代码 一、项目演示 项目演示地址&#xff1a; 视频地址 二、项目介绍 项目描述&#xff1a;这是一个基于SpringBootuniApp框架开发的宠物领养微信小程序系统。…

Elasticsearch的倒排索引是什么?

文章目录 什么是ES&#xff1f;什么是倒排索引&#xff1f;为什么叫做倒排索引&#xff1f;分词器的使用 什么是ES&#xff1f; Elasticsearch是基于 Apache Lucene【lusen】的搜索引擎&#xff0c;支持Restful API风格【可以使用常见的HTTP请求来访问】&#xff0c;并且搜索速…

在js中本地存储的数组如何转成对象

一、此方法仅适用一维数组&#xff1b; 二、效果图 使用后 三、js代码。 function gong(s){console.log(s);let data;let kk1;// 检查ask_id是否不为空 if (s.ask_id null ) { kk1}else{kk2let dd;dds.data;sessionStorage.setItem(wenda,JSON.stringify(dd[0]))window.l…

1、jvm基础知(一)

什么是JVM&#xff1f; 1、定义&#xff1a;JVM 指的是Java虚拟机&#xff08; Java Virtual Machine &#xff09;。JVM 本质上是一个运行在计算机上的程序&#xff0c; 他的职责是运行Java字节码文件&#xff0c;Java虚拟机上可以运行Java、Kotlin、Scala、Groovy等语言 任…

如何使用极狐GitLab Maven 仓库?

本文作者&#xff1a;徐晓伟 GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 本文主要讲述了如何使用极狐GitLa…

VSCode - 离线安装扩展python插件教程

1&#xff0c;下载插件 &#xff08;1&#xff09;首先使用浏览器打开 VSCode 插件市场link &#xff08;2&#xff09;进入插件主页&#xff0c;点击右侧的 Download Extension 链接&#xff0c;将离线安装包下载下来&#xff08;文件后缀为 .vsix&#xff09; 2&#xff0c;…

学透Spring Boot 003 —— Spring 和 Spring Boot 常用注解(附面试题和思维导图)

这是 学透 Spring Boot 专栏 的第三篇&#xff0c;欢迎关注我&#xff0c;与我一起学习和探讨 Spring Boot 相关知识&#xff0c;学透 Spring Boot。 从面试题说起 今天我们通过一道和Spring Boot有关的常见面试题入手。 面试题&#xff1a;说说 Spring Boot 中有哪些常用注解…

13.Python图形用户界面

我们之前的程序运行结果都被输出到命令提示符&#xff08;终端&#xff09;窗口&#xff0c;界 面比较简陋。本章讲解如何将其输出到图形界面。 1 Python中的图形用户界面开发库 注Qt是一个跨平台的C应用程序开发框架&#xff0c;被广泛用于开发GUI 程序&#xff0c;也可用于开…

OSPF协议详解

静态缺点 1、中大型复杂网络----配置量大 2、不能实时收敛 动态-----可以实时收敛 IGP----内部网关路由协议 RIP OSPF EIGRP ISIS EGP----外部网关路由协议 BGP IGP &#xff08;选路佳 占用资源 收敛快&#xff09;----一个协议好需满足这三个 距离矢量 DV RIP…

node.js的模块化 与 CommonJS规范

一、node.js的模块化 (1)什么是模块化&#xff1f; 将一个复杂的程序文件依据一定的规则拆分成为多个文件的过程就是模块化 在node.js中&#xff0c;模块化是指把一个大文件拆分成独立并且相互依赖的多个小模块&#xff0c;将每个js文件被认为单独的一个模块&#xff1b;模块…

HDLbits 刷题 -- Alwaysblock2

学习&#xff1a; For hardware synthesis, there are two types of always blocks that are relevant: Combinational: always (*)Clocked: always (posedge clk) Clocked always blocks create a blob of combinational logic just like combinational always blocks, but…

基于ArgoCD和Testkube打造GitOps驱动的Kubernetes测试环境

本文介绍了一项新工具&#xff0c;可以基于Gitops手动或者自动实现Kubernetes集群应用测试&#xff0c;确保集群的健康状态与Git仓库定义的一致。原文: GitOps-Powered Kubernetes Testing Machine: ArgoCD Testkube 简介&#xff1a;GitOps 云原生测试面临的挑战 现代云原生应…