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

快手一面-面经

1. RPC和Http的区别?

RPC(Remote Procedure Call,远程过程调用)和 HTTP(HyperText Transfer Protocol,超文本传输协议)是两种不同的通信机制,它们有不同的用途、工作原理和应用场景。以下是它们之间的主要区别:

1.1 目的和用途

RPC:RPC是一种协议,允许程序在不同的计算机之间调用远程系统上的函数或方法。RPC的主要目的是让远程调用的过程像本地调用一样简单,从而使分布式系统中的各个组件能够互相通信。它可以支持不同的传输协议(如HTTP、TCP、WebSocket等),并且常用于微服务架构中。
HTTP:HTTP是一种应用层协议,最初用于浏览器与Web服务器之间的通信。它是Web应用程序的基础,主要用于传输文本、图像、视频等数据内容。HTTP本身不涉及函数调用和远程过程,它主要用于请求和响应模式的数据传输。

1.2 工作原理

RPC:RPC让客户端调用远程计算机上的服务时,就像调用本地函数一样。客户端发送请求,服务器执行相应的操作,然后返回结果。RPC通常包括一个封装过程,即将函数参数进行序列化,然后通过网络发送给服务器,再由服务器反序列化并执行。常见的RPC框架有gRPC、Apache Thrift等。
HTTP:HTTP是基于请求-响应模型的协议。客户端发送HTTP请求(如GET、POST等),服务器处理请求并返回HTTP响应。HTTP通常使用JSON或XML作为数据格式进行数据交换。

1.3 协议的底层依赖

RPC:RPC可以在多种底层协议上运行,如HTTP、TCP、Unix套接字等,甚至可以跨语言传输。RPC框架通过封装和序列化函数调用的参数、结果及其类型信息来支持跨平台、跨语言调用。
HTTP:HTTP通常基于TCP/IP协议栈,但它本身不定义如何进行函数调用。它只是定义了如何传输数据,并主要用于Web服务的请求和响应。

1.4 数据交换格式

RPC:RPC框架通常采用高效的数据格式来传输数据,常见的格式有Protobuf(用于gRPC)和Thrift(用于Apache Thrift)。这些格式通常比传统的JSON和XML更高效,尤其是在需要高性能、低延迟的场景下。
HTTP:HTTP协议的数据通常是文本格式,最常见的格式是JSON或XML。JSON格式简洁易读,在Web开发中广泛使用。

1.5 易用性和开发复杂度

RPC:RPC提供了类似函数调用的接口,因此开发者不需要关心底层通信的细节。开发者只需要定义服务的接口,框架会自动处理序列化、网络通信等操作。不同的RPC框架(如gRPC、Thrift等)对开发者的友好度、功能支持等有所不同。
HTTP:HTTP通常更简单,尤其是在Web开发中,很多语言和框架提供了对HTTP协议的直接支持。它更适用于简单的请求-响应场景,但当涉及到复杂的远程过程调用时,可能需要额外的协议(如REST、GraphQL等)或工具来补充功能。

1.6 性能

RPC:通常,RPC比HTTP具有更好的性能,尤其是在调用的参数和结果需要高效传输时。RPC使用的二进制协议(如Protobuf)通常比文本协议(如JSON)更高效,占用更少的带宽和处理时间。
HTTP:HTTP本身传输的通常是文本格式(如JSON或XML),这意味着它的数据传输效率较低,尤其是在高频调用的场景下可能会成为性能瓶颈。

1.7 支持的场景

RPC:RPC通常用于服务间的高效、低延迟通信,特别是在微服务架构、分布式系统和高性能计算中。由于其高效的调用方式,RPC适合用于需要频繁和高效地调用远程服务的场景。
HTTP:HTTP通常用于Web应用程序、RESTful API、客户端和服务器之间的交互。HTTP是一种成熟的、广泛支持的协议,适用于跨平台、跨设备的应用场景,尤其在Web和移动应用中非常常见。

1.8 扩展性和兼容性

RPC:RPC框架通常提供语言支持的接口,且可以处理更多复杂的功能,如负载均衡、服务发现、认证等。不同的RPC框架可能对跨语言支持有所不同。
HTTP:HTTP具有良好的跨平台兼容性,几乎所有的设备和编程语言都支持HTTP。它的扩展性较强,尤其在Web开发和REST API中,HTTP可以轻松支持新的功能和特性。

总结

RPC: 是一种允许客户端调用远程服务的协议,强调高效、低延迟的远程过程调用,适合分布式系统和微服务架构。
HTTP: 是一种基于请求-响应模型的协议,广泛应用于Web通信,适合传输数据,尤其是通过RESTful API进行服务交互。

何时选择RPC,何时选择HTTP:

选择RPC: 当你需要高效的、低延迟的远程调用,并且系统涉及多个服务之间的频繁通信时,RPC是一个很好的选择,尤其是在微服务架构下。
选择HTTP: 如果你的应用场景是Web应用、移动应用或者简单的服务请求/响应交互,且需要良好的跨平台支持和兼容性,那么HTTP是最常见且合适的选择。

2. RPC比Http的优势在哪里?

在微服务架构中,Spring Cloud 是一个广泛使用的框架,它提供了很多功能,如服务发现、负载均衡、配置管理等。而在微服务之间的通信方式上,RPC 和 HTTP 各有其优劣。虽然 HTTP 作为 RESTful API 在微服务架构中非常流行,但 RPC(尤其是 gRPC 或其他高效的二进制协议)在某些场景下具有显著的优势。
RPC 相比 HTTP 在 Spring Cloud 微服务中的优势

2.1 高效的二进制协议

RPC:使用如 gRPC 这样的框架,RPC 通信通常基于高效的二进制协议(如 Protobuf)。这比 HTTP 使用的文本协议(如 JSON)要高效得多。二进制协议具有更小的数据包、更低的序列化/反序列化开销和更少的网络带宽消耗。
性能优势:在高频调用、高并发的场景下,RPC 提供了比 HTTP 更高的性能。
延迟低:由于数据传输量小,RPC 请求和响应的延迟通常较低,适合要求低延迟的微服务通信。
HTTP:HTTP 使用的 JSON 格式进行数据交换,比起二进制格式(如 Protobuf)在序列化/反序列化和传输上效率较低。

2.2 支持双向流通信(Streaming)

RPC(如 gRPC):支持双向流(bidirectional streaming),允许客户端和服务器之间进行持续的、双向的数据流通信。这对于需要实时数据交换和高频交互的场景(如实时监控、聊天应用、事件驱动架构等)非常有用。
双向流优势:客户端和服务端可以在单个连接中持续发送和接收数据,无需每次都重新建立连接。
HTTP:传统的 HTTP 请求响应模式只支持单向通信。虽然 WebSocket 和 HTTP/2 可以部分支持流式通信,但它们的实现和维护相对复杂,且无法提供与 gRPC 一样的高效双向流支持。

2.3 自动化的代码生成与接口定义

RPC:在 gRPC 或其他 RPC 框架中,服务接口通过 Protobuf 等工具定义,然后通过代码生成器自动生成客户端和服务器的代码。这使得服务接口的定义和实现非常简洁,而且可以保证客户端和服务端始终一致。
开发体验:开发人员可以专注于业务逻辑,不需要手动维护 HTTP 请求和响应的细节,减少了编码错误和不一致性。
HTTP:虽然 Spring Cloud 也提供了方便的工具来处理 HTTP API(例如通过 Spring MVC 定义 RESTful API),但它不如 RPC 那样能够自动化生成客户端和服务器代码,且需要开发人员手动维护 API 定义和实现。

2.4 强类型接口和高效的错误处理

RPC:在 gRPC 中,接口的定义是强类型的,且支持自动化的错误码管理和错误处理。开发人员可以清晰地定义每个 RPC 方法的输入输出类型,同时也能通过 Protobuf 生成的错误代码进行规范化处理。
HTTP:虽然 HTTP 也可以通过返回状态码来进行错误处理(如 4xx 和 5xx 错误码),但是它没有像 gRPC 那样强类型的接口支持。错误处理通常需要开发人员手动解析响应体中的错误信息,并且 JSON 格式可能带来一定的处理开销。

2.5 更好的服务发现与负载均衡

RPC:很多 RPC 框架(如 gRPC)集成了与服务发现和负载均衡相关的功能。通过与 Spring Cloud Eureka、Consul 或其他服务发现机制结合,RPC 可以自动发现目标服务并实现高效的负载均衡。
HTTP:虽然 Spring Cloud 也提供了 HTTP 的服务发现和负载均衡机制(如 Ribbon),但在实现上,RPC 协议往往更加轻量和高效,特别是在跨服务调用的高并发场景中。

2.6 跨语言支持

RPC:gRPC 和其他 RPC 框架通常提供了多语言支持,这使得你可以用不同的编程语言实现微服务。例如,可以用 Java 实现一个服务端,其他服务端可以用 Python、Go 等语言实现。这使得系统的跨语言协作更容易实现。
HTTP:虽然 HTTP 也可以跨语言支持,但它的协议本身并没有 RPC 那样针对服务调用进行优化。因此,跨语言时可能面临更多的转换和处理工作,尤其是在数据格式上。

2.7 兼容性和版本管理

RPC:在 gRPC 和类似的 RPC 框架中,版本管理非常清晰。通过 Protobuf 的 消息版本控制,你可以在不破坏旧版本接口的情况下,轻松增加新字段或方法,确保服务的向前兼容性和向后兼容性。
HTTP:HTTP 的版本管理往往通过 URL 路径(如 /v1/ 和 /v2/)进行,但对于复杂的数据模型或变化较大的接口,可能需要更多的手动管理,尤其是处理不同客户端兼容性时。

2.8 内建安全性和认证支持

RPC:许多 RPC 框架(如 gRPC)内建对 TLS/SSL 加密的支持,以及对 认证和授权 的支持。你可以很方便地集成 OAuth2、JWT 等安全机制。
HTTP:虽然 HTTP 也支持通过 SSL/TLS 实现加密,但认证和授权机制(如 OAuth2、JWT)通常需要额外的配置和集成。Spring Security 为 HTTP 提供了强大的支持,但其配置和实现可能比 RPC 更复杂。

总结:RPC 在 Spring Cloud 微服务架构中的优势

性能:RPC 使用二进制协议,比 HTTP 更高效,适合高并发、高频调用的场景。
低延迟:RPC 提供更低的通信延迟,适合对实时性要求较高的服务间通信。
双向流和实时通信:RPC 可以提供双向流通信,适合需要实时数据交换的场景。
自动化接口生成:RPC 框架可以通过接口定义自动生成客户端和服务端代码,简化开发。
强类型接口:RPC 提供强类型接口,有助于提高代码的安全性和可维护性。
服务发现与负载均衡:RPC 与服务发现和负载均衡的集成非常高效。
跨语言支持:RPC 的框架通常支持多种编程语言,适合异构系统。

当然,选择 RPC 还是 HTTP 需要根据具体的应用场景来决定。RPC 在高性能和高效通信的场景下非常有优势,而 HTTP(尤其是 RESTful API)则在易用性、跨平台兼容性和开发速度上有较大的优势。如果你使用 Spring Cloud,可以根据具体需求选择最适合的通信协议。

3.为什么在这个社交平台使用的是微服务架构呢?有什么考量吗?

在小红书这样一个大型社交平台中使用 微服务架构,是出于一系列技术、业务和运营上的考量。微服务架构可以帮助像小红书这样的应用系统应对其复杂的业务需求、规模扩展、以及不断变化的用户需求。以下是一些主要的考量因素:

3.1 系统复杂性和功能模块化

小红书作为一个综合性的社交平台,提供了诸如 内容创作、社交互动、电商交易、个性化推荐 等多个业务模块。这些模块往往具有不同的业务逻辑、技术需求和发展方向,传统的单体架构(Monolithic Architecture)可能会变得非常臃肿和难以维护。
模块化管理:微服务架构能够将这些复杂的业务功能拆分成多个独立的小服务,每个服务负责一个具体的业务功能。这样做不仅能提升代码的可维护性和可扩展性,还能减少模块之间的耦合,使得团队可以并行开发。
独立部署和开发:每个微服务都可以独立开发、测试和部署,避免了单体架构中对整个系统进行重构和重新部署时的风险和复杂性。

3.2 灵活的技术栈选择

小红书作为一个快速发展的平台,可能需要应对多种技术需求。微服务架构允许不同的服务使用不同的技术栈和工具,根据具体的业务需求进行优化。
技术多样性:例如,电商模块可能需要处理大量并发交易,适合使用高并发、高性能的技术栈;而社交互动部分可能更侧重于实时性和高可用性,可能采用不同的技术栈或数据库来支持。
技术独立性:每个微服务能够独立升级和演进,技术栈的更新不会影响到其他服务,支持快速适应技术发展的变化。

3.3 高可扩展性和高可用性

随着用户规模的增长和业务的不断扩展,小红书需要有能力应对不断增加的 流量、数据量 和 请求量。微服务架构的分布式特性能够提供更好的扩展性和容错能力。
按需扩展:微服务架构可以根据每个服务的负载情况进行单独的扩展。例如,社交互动模块可能需要更频繁的扩展来处理大量的实时消息和通知,而推荐算法模块则可能在高流量期间进行扩展来处理更多的个性化推荐请求。
容错和高可用性:如果某个微服务出现问题,不会影响到整个系统的运行。微服务可以通过负载均衡、自动故障转移和分布式容错机制确保高可用性。

3.4. 快速迭代与持续交付

社交平台如小红书需要频繁地推出新功能、优化现有功能、修复 Bug,并且还要快速响应用户的需求变化。微服务架构有助于加快产品迭代和发布频率。
独立部署与更新:每个微服务可以独立部署和更新,避免了整体系统更新的复杂性。这样,开发团队可以对每个微服务进行持续集成和持续交付,缩短发布周期。
敏捷开发:微服务架构支持敏捷开发方式,开发团队可以更加灵活地进行业务功能开发、测试和发布,从而更快速地响应市场需求。

3.5 跨团队协作与 DevOps 支持

小红书这样的大型平台,开发团队通常是跨职能、跨部门的,需要紧密协作。微服务架构为跨团队合作提供了很好的支持。
团队自治:每个微服务可以由独立的团队负责,团队可以独立选择技术栈、开发方式和发布周期。这促进了团队的自治性,减少了开发的依赖关系。
DevOps 支持:微服务架构与 DevOps 文化高度契合,支持自动化部署、持续集成、持续交付等。通过自动化的流水线,开发、测试、运维团队可以更高效地协作,确保系统的稳定和高效运营。

3.6 大规模用户和流量处理

小红书是一个庞大的社交平台,每天都有大量的用户产生互动、发布内容、浏览商品等。微服务架构通过服务拆分和分布式部署,能够有效地应对 海量用户并发 和 大数据处理。
高并发处理:小红书需要处理大量用户的访问请求和数据交互。通过微服务架构,可以将流量分散到不同的服务上,通过负载均衡来平衡压力,确保系统在高并发下依然能保持流畅。
数据分片与分布式存储:微服务架构可以将不同模块的数据分布在不同的数据库或存储系统中,从而提高数据访问速度和系统的伸缩性。

3.7 数据隐私与合规性

随着互联网用户数据量的增加,数据隐私和合规性成为了越来越重要的问题。微服务架构可以帮助小红书更好地管理用户数据,并确保各个服务符合不同区域的数据保护法规(如 GDPR、CCPA 等)。
数据隔离与安全:不同服务的数据可以隔离管理,避免单一服务泄露用户信息。此外,每个微服务可以独立管理数据加密、认证和访问控制,确保数据安全性。
合规性管理:微服务架构允许小红书更容易地应对不同地区的合规要求,数据存储和处理可以根据不同地区的法规进行调整。

3.8 事件驱动与异步处理

社交平台通常有大量的 异步事件(如用户点赞、评论、推送通知等)需要处理。微服务架构非常适合与 事件驱动架构 配合,能够高效处理这些异步任务。
消息队列:小红书可以通过消息队列(如 Kafka、RabbitMQ 等)在不同微服务之间传递事件,确保系统的松耦合和高效处理。
解耦与异步:微服务架构支持将一些长时间运行的任务(如视频处理、数据分析等)异步化,从而避免阻塞主线程,提高系统响应速度。

总结

小红书选择微服务架构的主要考量因素包括:
系统复杂性和模块化管理:通过微服务将不同业务模块分离,简化开发和维护。
高扩展性和高可用性:能够有效应对大量用户和流量的挑战,支持独立扩展和容错。
技术多样性:根据不同业务需求,灵活选择技术栈,优化系统性能。
快速迭代与持续交付:支持快速的产品更新和功能迭代,缩短开发周期。
跨团队协作与 DevOps:提高跨部门协作效率,支持自动化部署和持续集成。
数据隐私与合规性:通过数据隔离和安全控制,满足数据保护要求。

因此,微服务架构为小红书提供了 灵活性、可扩展性 和 高效的运维管理,帮助其在快速发展的过程中应对技术挑战,并确保平台的稳定性和用户体验。

4. 讲解一下redis当中的布隆过滤器

那问题来了,布隆过滤器是如何工作的呢?接下来,我介绍下。

布隆过滤器由「初始值都为 0 的位图数组」和「 N 个哈希函数」两部分组成。我们在写入数据库数据时,在布隆过滤器里做个标记,这样下次查询数据是否在数据库时,只需要查询布隆过滤器,如果查询到数据没有被标记,说明不在数据库中。
布隆过滤器会通过 3 个操作完成标记:

  • 第一步,使用 N 个哈希函数分别对数据做哈希计算,得到 N 个哈希值;
  • 第二步,将第一步得到的 N 个哈希值对位图数组的长度取模,得到每个哈希值在位图数组的对应位置。
  • 第三步,将每个哈希值在位图数组的对应位置的值设置为 1;
    在数据库写入数据 x 后,把数据 x 标记在布隆过滤器时,数据 x 会被 3 个哈希函数分别计算出 3 个哈希值,然后在对这 3 个哈希值对 8 取模,假设取模的结果为 1、4、6,然后把位图数组的第 1、4、6 位置的值设置为 1。当应用要查询数据 x 是否数据库时,通过布隆过滤器只要查到位图数组的第 1、4、6 位置的值是否全为 1,只要有一个为 0,就认为数据 x 不在数据库中。
    布隆过滤器由于是基于哈希函数实现查找的,高效查找的同时存在哈希冲突的可能性,比如数据 x 和数据 y 可能都落在第 1、4、6 位置,而事实上,可能数据库中并不存在数据 y,存在误判的情况。
    所以,查询布隆过滤器说数据存在,并不一定证明数据库中存在这个数据,但是查询到数据不存在,数据库中一定就不存在这个数据。

4.1 讲解一下在点赞过程中使用布隆过滤器是干什么呢?

笔记点赞流程设计为:
在这里插入图片描述
笔记点赞接口的处理流程如下:

  • 判断被点赞的笔记是否真实存在,若不存在,则返回提示信息:笔记不存在;
  • 判断笔记是否被点赞过,若已点赞,则返回提示信息:该篇笔记已点赞;
  • 判断用户的 ZSET 点赞列表是否存在,若存在,再判断 ZSET 的大小已经达到 100(每页10条,共10页的数据):
    • 若达到,则向 ZSET 中添加最新的点赞笔记,并将点赞时间最久的那篇,移除出 ZSET;
    • 若未达到,则直接向 ZSET 中添加最新的点赞笔记;
  • 发送 MQ, 让消费者去将点赞记录存入 t_note_like 表中;

4.2 在点赞这个用户行为中为什么呢要使用布隆过滤器

  • 实现原理: 由于 Redis Set 在存储大量用户数据时可能导致较高的内存消耗,使用 布隆过滤器(Bloom Filter)可以有效地减少存储空间。布隆过滤器可以用来快速判断一个用户是否可能已经点赞过该笔记,但可能会存在少量误报(false positive)。
  • 操作步骤:
  1. 为每个用户点赞列表初始化一个布隆过滤器,并在每次点赞笔记时,将笔记 ID 入到该布隆过滤器中;
  2. 使用 Bloom Filter 的 BF.EXISTS 命令判断笔记是否已经点赞过;
  3. 如果返回未点赞(不存在误报),则继续执行后续点赞逻辑;若返回已点赞(可能有误报),则需要进一步确认是否已点赞。
  • 优点:显著减少内存消耗,适合海量用户场景。
  • 缺点:对于已点赞笔记,存在一定的误判(对未点赞的笔记判断,则绝对正确)。

5.使用 Redis ZSET + MQ 异步落库怎样做的,目的是什么

5.1 为什么使用Zset

首先 Zset可以按照某种顺序进行排列
在点赞这个用户行为中,执行Lua脚本,并使用 Zset 对数据进行添加,若点赞数据已经存在,那么 Zset会按照点赞数目进行排序。

5.2 Zset底层是如何实现的

Zset 类型的底层数据结构是由压缩列表或跳表实现的:

  • 如果有序集合的元素个数小于 128 个,并且每个元素的值小于 64 字节时,Redis 会使用压缩列表作为 Zset 类型的底层数据结构;
  • 如果有序集合的元素不满足上面的条件,Redis 会使用跳表作为 Zset 类型的底层数据结构;
    在 Redis 7.0 中,压缩列表数据结构已经废弃了,交由 listpack 数据结构来实现了。

5.3 跳表是怎么实现的?

链表在查找元素的时候,因为需要逐一查找,所以查询效率非常低,时间复杂度是O(N),于是就出现了跳表。跳表是在链表基础上改进过来的,实现了一种「多层」的有序链表,这样的好处是能快读定位数据。
那跳表长什么样呢?我这里举个例子,下图展示了一个层级为 3 的跳表。
在这里插入图片描述
图中头节点有 L0~L2 三个头指针,分别指向了不同层级的节点,然后每个层级的节点都通过指针连接起来:

  • L0 层级共有 5 个节点,分别是节点1、2、3、4、5;
  • L1 层级共有 3 个节点,分别是节点 2、3、5;
  • L2 层级只有 1 个节点,也就是节点 3 。
    如果我们要在链表中查找节点 4 这个元素,只能从头开始遍历链表,需要查找 4 次,而使用了跳表后,只需要查找 2 次就能定位到节点 4,因为可以在头节点直接从 L2 层级跳到节点 3,然后再往前遍历找到节点 4。
    可以看到,这个查找过程就是在多个层级上跳来跳去,最后定位到元素。当数据量很大时,跳表的查找复杂度就是 O(logN)。
    那跳表节点是怎么实现多层级的呢?这就需要看「跳表节点」的数据结构了,如下:

详情见小林Coding Redis章节 : 跳表是怎么实现的?

6.Redis中的IO复用了解过吗?

解析见:Redis怎么实现的io多路复用?

7. Java 中的 Set 结构:底层实现、常见问题及解决方案

7.1. Set 的主要实现类及其底层实现

7.1.1 HashSet

  • 底层实现
    HashSet 是基于 HashMap 实现的。具体来说,HashSet 内部使用一个 HashMap 来存储元素,其中每个元素作为 HashMap 的 key,而 value 则是一个固定值(通常是一个占位符对象)。
  • 特点
    • 元素的存储顺序不保证。
    • 使用哈希表存储元素,依赖元素的 hashCode()equals() 方法来判断元素是否重复。
    • 如果发生哈希冲突,HashSet 使用链表或红黑树解决冲突(从 Java 8 开始,当冲突链表长度超过阈值时,会转为红黑树)。
  • 时间复杂度
    • 插入、删除、查找:平均 O(1),最坏情况(哈希冲突严重):O(n)

7.1.2 TreeSet

  • 底层实现
    TreeSet 是基于 TreeMap 实现的,其底层是一个红黑树。
  • 特点
    • 元素会按自然顺序(或通过提供的比较器)排序。
    • 判断重复依赖于 compareTo() 或比较器的 compare() 方法,而不是 hashCode()equals()
  • 时间复杂度
    • 插入、删除、查找:O(log n),因为红黑树的高度是对数级别。

7.1.3 LinkedHashSet

  • 底层实现
    LinkedHashSet 是基于 HashMap 和双向链表实现的,它继承了 HashSet 的特点,并通过双向链表维护元素的插入顺序。
  • 特点
    • 保证了元素的迭代顺序与插入顺序一致。
    • 其判断重复的方式与 HashSet 相同(依赖 hashCode()equals())。
  • 时间复杂度
    • 插入、删除、查找:O(1),与 HashSet 类似,但由于维护了插入顺序,实际开销稍大。

7.2. Set 常见问题及解决方案

7.2.1 重复元素判断问题

  • 问题
    对于 HashSetLinkedHashSet,重复元素的判断依赖于 hashCode()equals() 方法。如果这两个方法未正确实现(例如,对于自定义对象,没有重写 hashCode()equals()),则可能导致重复元素无法被正确识别。
  • 解决方法
    • 为自定义对象重写 hashCode()equals() 方法。
    • hashCode() 的实现应尽量分布均匀,以减少哈希冲突。
    • equals() 的实现需要满足自反性、对称性、传递性和一致性。

7.2.2 哈希冲突问题

  • 问题
    HashSet 中,如果多个元素的 hashCode() 值相同(发生哈希冲突),它们会被存储在同一个桶中,影响性能。
  • 解决方法
    • 重写 hashCode() 方法,确保哈希值分布均匀。
    • 从 Java 8 开始,HashSet 在哈希冲突时会使用红黑树优化性能(当冲突链表长度超过 8 时),降低最坏情况的时间复杂度。

7.2.3 顺序问题

  • 问题
    HashSet 中,元素的存储顺序是不可预测的,因此如果需要有序存储(例如按插入顺序或按某种比较规则),HashSet 不适用。
  • 解决方法
    • 如果需要按插入顺序存储,使用 LinkedHashSet
    • 如果需要按自然顺序或自定义顺序存储,使用 TreeSet

7.2.4 性能问题

  • 问题
    在高并发场景下,HashSetTreeSet 是线程不安全的,可能会导致数据不一致或异常。
  • 解决方法
    • 使用 Collections.synchronizedSet() 方法来包装 HashSetTreeSet,使其线程安全。
    • 或者,使用 ConcurrentSkipListSet,它是线程安全的,底层基于跳表实现,适合并发场景。

7.3. Set 时间复杂度总结

操作HashSetTreeSetLinkedHashSet
插入元素平均 O(1)O(log n)平均 O(1)
删除元素平均 O(1)O(log n)平均 O(1)
查找元素平均 O(1)O(log n)平均 O(1)
遍历所有元素O(n)O(n)(按顺序)O(n)(按插入顺序)

7.4. 总结和适用场景

  • HashSet

    • 优点:快速访问(O(1))。
    • 缺点:不保证顺序。
    • 适用场景:需要快速去重的集合操作,且对顺序无要求。
  • TreeSet

    • 优点:有序集合(按自然顺序或自定义比较器)。
    • 缺点:性能略低于 HashSet,插入和删除操作需要维护红黑树(O(log n))。
    • 适用场景:需要有序存储或快速范围查询的场景。
  • LinkedHashSet

    • 优点:既有 HashSet 的高性能,又能维护插入顺序。
    • 缺点:比 HashSet 占用更多的内存。
    • 适用场景:需要快速访问且需要维护插入顺序的场景。

根据实际需求选择合适的 Set 实现,正确设计 hashCode()equals() 方法,并在必要时优化性能(如减少哈希冲突),即可充分发挥 Set 的优势。

8. 线程池情景题:目前有10个线程,线程1还未执行完,线程2-10已经到达。核心线程数是3,最大线程数是6,组合队列是3。那么从线程1到线程10是怎样一个执行过程?

组合队列的作用

线程池 中,组合队列(也就是任务队列)的作用非常重要。队列的主要功能是:

  1. 缓存等待执行的任务:如果线程池中的线程数已经达到最大线程数,接下来的任务会被放入队列中,等待空闲线程来执行。
  2. 控制并发:队列容量的限制有助于限制并发任务的数量,从而防止线程池创建过多线程,过度消耗系统资源。

组合队列在这个情境中的作用

根据题目,线程池的配置如下:

  • 核心线程数:3
  • 最大线程数:6
  • 队列容量(组合队列):3

这意味着:

  • 线程池可以同时运行 3个核心线程,并且如果核心线程有空闲,它会自动创建新线程,直到达到 最大线程数(6个线程)
  • 一旦达到最大线程数,后续的任务会进入 队列(最多能容纳 3个任务)。

具体执行过程中的队列作用

1. 线程池的初期执行(线程1到线程3)

  • 线程1开始执行(核心线程1)。
  • 随后,线程2线程3到达,线程池会分配这两个任务到 空闲的核心线程2和线程3
  • 此时线程池中的 3个核心线程(线程1、线程2、线程3)都在工作,队列为空。

2. 新任务到达,线程池达到最大线程数(线程4到线程6)

  • 线程4、线程5、线程6到达。此时,线程池已经有 3个核心线程(线程1、线程2、线程3)在工作,且核心线程数已满。由于线程池的 最大线程数为6,线程池会启动新的线程来执行任务。
  • 所以,线程池会分配 线程4线程5线程6 到新创建的线程,线程池现在有 6个线程在工作(线程1到线程6)。

3. 队列的作用(线程7到线程9)

  • 线程7、线程8、线程9到达。此时,线程池已经有 6个线程在运行,达到了最大线程数,线程池无法再创建新的线程来处理任务。
  • 由于队列容量为 3线程7、线程8、线程9 将被 放入队列中,等待空闲的线程来执行。
  • 这时候,线程池内部的情况是:6个线程(线程1到线程6)在执行任务,且 队列中有3个任务(线程7到线程9),等待执行。

4. 空闲线程回收和队列中任务的执行

  • 线程1、线程2和线程3先后完成。由于线程池的 核心线程数为3,这些线程完成后会保持空闲,等待新的任务。如果任务队列中有待执行的任务,它们会被分配给空闲的线程。
  • 于是,线程7 会被分配给空闲的线程1(假设线程1空闲),然后 线程8 会被分配给线程2,依此类推,直到队列中的任务(线程7、线程8、线程9)都被执行完。

5. 线程10的执行

  • 线程4、线程5、线程6 完成后,线程池就会从队列中取出 线程10 来执行,直到所有任务完成。

关键点总结

  • 组合队列 在这个情景中的作用是 缓存 待执行的任务。当线程池中的活跃线程数达到最大线程数(6个线程)时,后续到达的任务会被放入队列中,等待有空闲线程时再执行。
  • 队列的容量限制了队列中最多能有多少个任务(在本题中为3个),这是防止系统过载的一个重要机制。
  • 队列的容量线程池的最大线程数共同决定了线程池的并发执行能力。队列满时,任务会被阻塞,直到有空闲线程可以继续执行队列中的任务。

总结:

  • 线程池会优先使用核心线程数来执行任务,直到达到最大线程数。
  • 一旦线程池达到最大线程数,后续的任务会被放入队列(最多3个任务),等待线程池中的线程空闲后才会继续执行队列中的任务。
  • 队列的作用是缓存等待的任务并避免过多线程的创建,它保证了线程池的任务管理与资源使用之间的平衡。

9. 在MySQL中B树和B+树的区别以及B+ 树的优势

详情请见如下回答:说说B+树和B树的区别

相关文章:

快手一面-面经

1. RPC和Http的区别? RPC(Remote Procedure Call,远程过程调用)和 HTTP(HyperText Transfer Protocol,超文本传输协议)是两种不同的通信机制,它们有不同的用途、工作原理和应用场景…...

<style lang=“scss“ scoped>: 这是更常见的写法,也是官方文档中推荐的写法

这两种写法在大多数情况下是没有区别的&#xff0c;它们都是 Vue.js 单文件组件 (.vue 文件) 中用来定义组件私有样式的方式。 两种写法&#xff1a; <style lang"scss" scoped>: 这是更常见的写法&#xff0c;也是官方文档中推荐的写法。<style scoped l…...

cerebro关闭ssl

cerebro连接es报错 io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: (certificate_unknown) Received fatal alert: certificate_unknown 在cerebro的application.conf配置文件中添加 play.ws.ssl.loose.acceptAnyCertificate true Disab…...

网络安全常见的问题

1. 什么是 DDoS 攻击&#xff1f;如何防范&#xff1f; 答&#xff1a;DDoS 攻击是指利用大量的计算机或者其他网络设备&#xff0c;同时向目标网络或者服务器 发送 大量的数据流量&#xff0c;以致其无法正常工作&#xff0c;从而导致网络瘫痪或者服务器宕机的攻击行 为。 …...

Eclipse配置Tomcat服务器(最全图文详解)

前言&#xff1a; 本章使用图文讲解如何在Eclipse开发工具中配置Tomcat服务器、如何创建和启动JavaWeb工程&#xff0c;欢迎童鞋们互相交流。觉得不错可以三连订阅喔。 目标&#xff1a; 一、配置Tomcat服务器 1. 切换Eclipse视图 2. 打开菜单 3. 找到服务选项 4. 选择…...

mv指令详解

&#x1f3dd;️专栏&#xff1a;https://blog.csdn.net/2301_81831423/category_12872319.html &#x1f305;主页&#xff1a;猫咪-9527-CSDN博客 “欲穷千里目&#xff0c;更上一层楼。会当凌绝顶&#xff0c;一览众山小。” 目录 基本语法 主要功能 常用选项详解 1. …...

SQL从入门到实战

学前须知 sqlzoo数据介绍 world nobel covid ge game、goal、eteam teacher、dept movie、casting、actor 基础语句 select&from SELECT from WORLD Tutorial - SQLZoo 基础查询select单列&多列&所有列&别名应用 例题一 SELECT name, continent, population …...

回归中医传统 重铸中医之魂 — 薛应中 —

最近做了一个20次课的讲义纲要,每节课都是中医理念下某一类疾病的认知与诊疗,或是一个重大健康观念的辨析,准备陆续和各届人士一起探讨。 下面就算是一个序言,主要是做一个自我介绍,将自己的一点心得,结合我的行医经历,以及学习中医的治学之道等,做一个开场白。 (一)中医的有…...

什么是面向对象?

面向对象编程&#xff08;Object-Oriented Programming&#xff0c;简称OOP&#xff09;是一种流行的编程方法&#xff0c;它以对象和类为基础构建软件。该编程范式围绕“对象”这一基本概念展开&#xff0c;其中对象被视为包含数据和行为的软件构件。以下是对面向对象编程的深…...

HDFS读写流程

因为namenode维护管理了文件系统的元数据信息&#xff0c;这就造成了不管是读还是写数据都是基于NameNode开始的&#xff0c;也就是说NameNode成为了HDFS访问的唯一入口。入口地址是&#xff1a;http://nn_host:8020。 一、写数据流程 1.1 Pipeline管道、ACK应答响应 Pipeline…...

HDFS Federation联邦机制

一、当前HDFS体系架构 1.1 简介 当前的HDFS架构有两个主要的层&#xff1a; 命名空间&#xff08;namespace&#xff09; HDFS体系结构中的命名空间层由文件&#xff0c;块和目录组成。该层支持与名称空间相关的文件系统操作&#xff0c;例如创建&#xff0c;删除&#xff0…...

机器学习周报-ModernTCN文献阅读

文章目录 摘要Abstract 0 提升有效感受野&#xff08;ERF&#xff09;1 相关知识1.1 标准卷积1.2 深度分离卷积&#xff08;Depthwise Convolution&#xff0c;DWConv&#xff09;1.3 逐点卷积&#xff08;Pointwise Convolution&#xff0c;PWConv&#xff09;1.4 组卷积(Grou…...

QT RC_FILE 应用程序图标设置

1.先做一个app.ico 文件&#xff0c;并将文件放入资源文件夹中 2.打开QT项目的.pro文件在最下面增加 RC_FILE $$PWD/res/app.rc 3.在资源文件夹中创建一个app.rc文件。在QT开发工具中编辑并输入下在内容 IDI_ICON1 ICON "app.ico" 4.测试效果...

5G学习笔记之SNPN系列之网络选择

目录 0. NPN系列 1. 概述 2. 自动网络选择 3. 手动网络选择 0. NPN系列 1. NPN概述 2. NPN R18 3. 【SNPN系列】SNPN ID和广播消息 4. 【SNPN系列】UE入网和远程配置 5. 【SNPN系列】SNPN选择 6. PNI-NPN 1. 概述 对于某个特定的UE&#xff0c;可以仅支持SNPN接入模式&#x…...

k8s helm部署kafka集群(KRaft模式)——筑梦之路

添加helm仓库 helm repo add bitnami "https://helm-charts.itboon.top/bitnami" --force-update helm repo add grafana "https://helm-charts.itboon.top/grafana" --force-update helm repo add prometheus-community "https://helm-charts.itboo…...

Redis学习笔记

目录 Nosql概述 为什么用Nosql 什么是Nosql Nosql四大分类 Redis入门 概述 Windows安装 Linux安装 测试性能 基础知识 五大数据类型 Redis-Key String(字符串) List&#xff08;列表&#xff09; Set(集合) Hash&#xff08;哈希&#xff09; Zset&#xff08;有…...

mysql递归查询语法WITH RECURSIVE

WITH RECURSIVE 是 SQL 中用于执行递归查询的语法&#xff0c;特别适合于处理层级结构或递归数据&#xff08;如树形结构、图结构&#xff09;。递归查询可以反复引用自己来查询多层次的数据&#xff0c;而无需写多个嵌套查询。 基本语法结构&#xff1a; WITH RECURSIVE CTE…...

Go语言之十条命令(The Ten Commands of Go Language)

Go语言之十条命令 Go语言简介 Go语言&#xff08;又称Golang&#xff09;‌是由Google开发的一种开源编程语言&#xff0c;首次公开发布于2009年。Go语言旨在提供简洁、高效、可靠的软件开发解决方案&#xff0c;特别强调并发编程和系统编程‌。 Go语言的基本特征 ‌静态强类…...

Visual Studio 2022 C++ gRPC 环境搭建

文章目录 1、gRPC 安装2、创建项目2.1、创建 “空的解决方案”2.2、新建 gRPCServer 和 gRPCClient 项目2.3、创建 proto 文件 2、为 gRPC 服务端和客服端项目配置 protobuf 编译2.1、protobuf 配置2.2、gRPCServer 项目配置2.3、gRPCClient 项目配置 3、测试3.1、启动服务端程…...

2024AAAI SCTNet论文阅读笔记

文章目录 SCTNet: Single-Branch CNN with Transformer Semantic Information for Real-Time Segmentation摘要背景创新点方法Conv-Former Block卷积注意力机制前馈网络FFN 语义信息对齐模块主干特征对齐共享解码头对齐 总体架构backbone解码器头 对齐损失 实验SOTA效果对比Cit…...

【Java从入门到放弃 之 final 关键字】

final 关键字 final 关键字final 字段final 函数列表中的参数final 方法final 类 final 关键字 Java中里面有final这个关键字&#xff0c;这个关键字总体上是用来表达” 不能被改变“ 这个意思的。我们使用这个关键字表达不能被改变&#xff0c;有两种使用场景&#xff0c;有三…...

【U8+】用友U8软件中,出入库流水输出excel的时候提示报表输出引擎错误。

【问题现象】 通过天联高级版客户端登录拥有U8后&#xff0c; 将出入库流水输出excel的时候&#xff0c;提示报表输出引擎错误。 进行报表输出时出现错误&#xff0c;错误信息&#xff1a;找不到“fd6eea8b-fb40-4ce4-8ab4-cddbd9462981.htm”。 如果您正试图从最近使用的文件列…...

文本区域提取和分析——Python版本

目录 1. 图像预处理 2. 文本区域提取 3. 文本行分割 4. 文本区域分析 5. 应用举例 总结 文本区域提取和分析是计算机视觉中的重要任务&#xff0c;尤其在光学字符识别&#xff08;OCR&#xff09;系统、文档分析、自动化数据录入等应用中有广泛的应用。其目标是从图像中提…...

数据库介绍(不同数据库比较)

文章目录 **一、关系型数据库&#xff08;RDBMS&#xff09;****1. MySQL****优点**&#xff1a;**缺点**&#xff1a;**适用场景**&#xff1a; **2. PostgreSQL****优点**&#xff1a;**缺点**&#xff1a;**适用场景**&#xff1a; **3. Oracle Database****优点**&#xff…...

注意力的简单理解,有哪些注意力(Attention)

注意力(Attention) 目录 注意力(Attention)掩码注意力机制自注意力、交叉注意力、掩码注意力的不同点适应场景及举例多头注意分层注意力(Hierarchical Attention)协同注意力(Co - Attention)自注意力(Self - Attention) 简单理解:自注意力就像是一个句子(或序列)内…...

基于Python的投资组合收益率与波动率的数据分析

基于Python的投资组合收益率与波动率的数据分析 摘要&#xff1a;該文通过研究马科维茨的投资组合模型&#xff0c;并将投资组合模型应用到包含6只金融股票的金融行业基金中。首先通过开源的财经接口Tushare获取股票原始数据&#xff0c;接着利用数据分析的黄金组合库&#xf…...

《Opencv》图像的旋转

一、使用numpy库实现 np.rot90(img,-1) 后面的参数为-1时事顺时针旋转&#xff0c;为1时是逆时针旋转。 import cv2 import numpy as np img cv2.imread(./images/kele.png) """方法一""" # 顺时针90度 rot_1 np.rot90(img,-1) # 逆时针90度…...

Python 22:注释

1. 定义&#xff1a; 用熟悉的语言对代码进行解释说明。注释不会被执行。 2. 注释分类 单行注释&#xff1a;只能对一行代码进行注释。放在要注释的代码后面&#xff0c;用#进行分隔&#xff0c;中间至少空2个空格&#xff0c;保证代码规范。 print("hello world10"…...

python:利用神经网络技术确定大量离散点中纵坐标可信度的最高集中区间

当我们有许多离散点并想要确定纵坐标在某个区间内的可信度时&#xff0c;我们可以使用神经网络模型来解决这个问题。下面是一个使用Python编写的示例代码&#xff0c;展示了如何使用神经网络来确定大量离散点中纵坐标可信度的最高集中区间。 import numpy as np from sklearn.…...

计算机软件保护条例

(2001年12月20日中华人民共和国国务院令第339号公布 根据2011年1月8日《国务院关于废止和修改部分行政法规的决定》第一次修订 根据2013年1月30日《国务院关于修改〈计算机软件保护条例〉的决定》第二次修订) 第一章 总则 第一条 为了保护计算机软件著作权人的权益&#…...

CM3/4启动流程

CM3/4启动流程 1. 启动模式2. 启动流程 1. 启动模式 复位方式有三种&#xff1a;上电复位&#xff0c;硬件复位和软件复位。 当产生复位&#xff0c;并且离开复位状态后&#xff0c;CM3/4 内核做的第一件事就是读取下列两个 32 位整数的值&#xff1a; 从地址 0x0000 0000 处取…...

gaussdb中怎么查询一个表有多少GB

在 GaussDB 中&#xff0c;你可以通过多种方法查询一个表的大小&#xff0c;包括使用系统视图和内置函数。以下是几种常见的方法&#xff1a; 1. 使用 pg_total_relation_size 函数 pg_total_relation_size 函数返回一个表及其所有索引和 TOAST 数据的总大小。 示例查询 SE…...

2025-01-06 Unity 使用 Tip2 —— Windows、Android、WebGL 打包记录

文章目录 1 Windows2 Android2.1 横版 / 竖版游戏2.2 API 最低版本2.3 目标帧率2.3.1 targetFrameRate2.3.2 vSyncCount2.3.3 Unity 默认设置以及推荐设置2.3.4 Unity 帧率托管 3 WebGL3.1 平台限制3.2 打包报错记录 13.3 打包报错记录 2 ​ 最近尝试将写的小游戏打包&#xff…...

OP-TEE环境飞腾密码引擎编程指南

【写在前面】 飞腾开发者平台是基于飞腾自身强大的技术基础和开放能力&#xff0c;聚合行业内优秀资源而打造的。该平台覆盖了操作系统、算法、数据库、安全、平台工具、虚拟化、存储、网络、固件等多个前沿技术领域&#xff0c;包含了应用使能套件、软件仓库、软件支持、软件适…...

解密Navicat密码(Java)

最近从Navicat换到了DBeaver&#xff0c;导出配置文件发现配置文件里的密码都是加密的&#xff0c;看网上的都是给的PHP代码&#xff0c;因为环境问题&#xff0c;就算是在线上运行的PHP代码也会报错&#xff0c;所以就把这段代码改成Java了。 package com.unicdata.system.con…...

apex安装

安装过程复杂曲折&#xff0c;网上说的很多办法&#xff0c;貌似成功了&#xff0c;实际还是没起作用。 先说成功过程&#xff0c;执行下面命令&#xff0c;安装成功&#xff08;当然&#xff0c;前提是你要先配置好编译环境&#xff09;&#xff1a; &#xff08;我的环境&a…...

常见的开源网络操作系统

常见的开源网络操作系统有很多,它们通常用于路由器、交换机、网络设备和服务器等场景,具有灵活、可定制、易于扩展的特点。以下是一些常见的开源网络操作系统: OpenWRT 用途:主要用于路由器、无线接入点和网络设备。提供了广泛的定制选项和高级功能,如防火墙配置、VPN 支持…...

2024年6月英语六级CET6听力原文与解析

目录 0 序言 1.Long Conversation(长对话) 1.1 Blender 搅拌机 1.2 村庄的改造变化 2.Passage 2.1 micro robots 微型机器人 2.2 elite sleeper 睡眠精英 3.Lecture 3.1 对自身观念变化的低察觉度及相关研究发现 3.2 美国母亲群体数量变化及母亲节消费趋势分析 3.3 …...

力扣2-回文数

一.题目 给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。 例如&#xff0c;121 是回文&…...

基于springboot的网上商城购物系统

作者&#xff1a;学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等 文末获取“源码数据库万字文档PPT”&#xff0c;支持远程部署调试、运行安装。 目录 项目包含&#xff1a; 开发说明&#xff1a; 系统功能&#xff1a; 项目截图…...

业务日志设计

当一个项目足够大的时候&#xff0c;我们需要将统计系统完全独立出去&#xff0c;那么就无法避免数据采集的问题&#xff0c;我们可以在业务触发处增加log日志来记录当前变化的原始数据&#xff0c;提供统计系统进行采集 设计一个统计系统的日志记录机制时&#xff0c;主要需要…...

梯度下降方法

2.5 梯度下降方法介绍 学习目标 掌握梯度下降法的推导过程知道全梯度下降算法的原理知道随机梯度下降算法的原理知道随机平均梯度下降算法的原理知道小批量梯度下降算法的原理 上一节中给大家介绍了最基本的梯度下降法实现流程&#xff0c;本节我们将进一步介绍梯度下降法的详细…...

javascript

引入方式 JavaScript 程序不能独立运行&#xff0c;它需要被嵌入 HTML 中&#xff0c;然后浏览器才能执行 JavaScript 代码。通过 script 标签将 JavaScript 代码引入到 HTML 中&#xff0c;有两种方式&#xff1a; 内部方式 通过 script 标签包裹 JavaScript 代码 <!DO…...

大语言模型训练所需的最低显存,联邦大语言模型训练的传输优化技术

联邦大语言模型训练的传输优化技术 目录 联邦大语言模型训练的传输优化技术大语言模型训练所需的最低显存大语言模型训练所需的最低显存 基于模型微调、压缩和分布式并行处理的方法,介绍了相关开源模型及技术应用 核心创新点 多维度优化策略:综合运用基于模型微调、模型压缩和…...

二叉树的二叉链表和三叉链表

在二叉树的数据结构中&#xff0c;通常有两种链表存储方式&#xff1a;二叉链表和三叉链表。这里&#xff0c;我们先澄清一下概念&#xff0c;通常我们讨论的是二叉链表&#xff0c;它用于存储二叉树的节点。而“三叉链表”这个术语在二叉树的上下文中不常见&#xff0c;可能是…...

api开发如何在代码中使用京东商品详情接口的参数?

选择编程语言和相关工具 以 Python 为例&#xff0c;你可以使用requests库来发送 HTTP 请求获取接口数据。如果是 Java&#xff0c;可以使用OkHttp等库。 Python 示例 假设你已经安装了requests库&#xff0c;以下是一个简单的代码示例来获取和使用京东商品详情接口参数&#…...

Quartz如何实现分布式调度

系列文章目录 任务调度管理——Quartz入门 Quartz如何实现分布式控制 系列文章目录一、持久化二、分布式调度1. 表信息2. 调度器的竞争3. 触发器的分配 三、 总结 我们都说Quartz是个分布式调度框架&#xff0c;那么在分布式环境上&#xff0c;如何使得各个服务器上的定时任务…...

JUC--线程池

线程池 七、线程池7.1线程池的概述7.2线程池的构建与参数ThreadPoolExecutor 的构造方法核心参数线程池的工作原理 Executors构造方法newFixedThreadPoolnewCachedThreadPoolnewSingleThreadExecutornewScheduledThreadPool(int corePoolSize) 为什么不推荐使用内置线程池&…...

以柔资讯-D-Security终端文件保护系统 logFileName 任意文件读取漏洞复现

0x01 产品简介 D-Security终端文件保护系统是一套专注于企业文件管理效率与安全的解决方案,统对文件进行全文加密,而非仅在文件表头或特定部分进行加密,从而大大提高了文件的安全性,降低了被破解的风险。D-Security终端文件保护系统是被政府和国安局等情报单位唯一认定的安…...

【JavaScript】Set,Map,Weakmap

以下来源&#xff1a;九剑科技。 weakmap WeakMap是 ES6 中新增的一种集合类型&#xff0c;叫做“弱映射”&#xff0c;由于他的键引用的对象是弱引用&#xff0c;键所指向的对象可以被垃圾回收&#xff0c;可以防止内存泄露。 map ①Map是键值对的集合&#xff0c;键值不限…...