面试系列-携程暑期实习一面

news2024/11/19 2:29:20

Java 基础

1、Java 中有哪些常见的数据结构?

图片来源于:JavaGuide

Java集合框架图
Java集合框架图

Java 中常见的数据结构包含了 List、Set、Map、Queue,在回答的时候,只要把经常使用的数据结构给说出来即可,不需要全部记住

如下:

List 列表: 有 ArrayList、LinkedList

1、ArrayList 是动态数组

2、LinkedList 是双向链表

Set 集合: 有 HashSet、LinkedHashSet、TreeSet

1、HashSet 基于 HashMap 实现,不保证元素的顺序,利用 Map 的 key 不能重复保证元素的唯一性

2、LinkedHashSet 继承自 HashSet,基于 LinkedHashMap 实现,通过链表维护元素的插入顺序

3、TreeSet 基于红黑树实现,元素自然排序或指定排序器排序

Map 哈希映射: 有 HashMap、LinkedHashMap、TreeMap、ConcurrentHashMap

1、HashMap 基于数组+链表+红黑树实现

2、LinkedHashMap 继承自 HashMap,通过链表维护元素插入顺序

3、TreeMap 基于红黑树实现,会对元素的 key 进行自然排序或指定排序器排序

4、ConcurrentHashMap 并发安全的 HashMap,在 JDK1.8 及以后通过 CAS + synchronized 实现线程安全

Queue 队列: 有 PriorityQueue、ArrayDeque

1、PriorityQueue 基于优先级堆的优先队列实现,元素自然排序或指定排序器排序

2、ArrayDeque 基于数组的双端队列

2、HashMap 介绍一下,key 可以设置为 null 吗?

HashMap 是哈希结构,存储 k-v 键值对,底层实现的话由数组+链表+红黑树进行实现

HashMap 中是可以存储 null 的 key 或 value 的,在 HashMap 中,为 null 的 key 只有一个,当传入 key 为 null 的时候,就会返回数组中索引为 0 的位置

3、ConcurrentHashMap 的 key 可以为 null 吗?

在 ConcurrentHashMap 中的 key 和 value 是不可以为 null 的

大家可以思考一下,为什么 HashMap 中 key 可以为 null,ConcurrentHashMap 中不可以呢?

ConcurrentHashMap 是并发安全的,因此是在多线程环境中使用的,如果 key 或者 value 可以为 null 的话,那么就会存在 二义性

因为一个线程在操作 ConcurrentHashMap 的时候,其他线程也有可能同时来进行修改,因此会存在 二义性 的问题:

如果 key 为 null,就无法区分这个 key 是否存在于 ConcurrentHashMap 中;如果 value 为 null,就无法区分这个 value 是不存在 ConcurrentHashMap 中还是该 value 被置为了 null

HashMap 中的 key 和 value 为什么可以为 null?

而 HashMap 中的 key 和 value 可以为 null 就是因为 HashMap 是并发不安全的,因此使用 HashMap 的话,都是在单线程环境下使用,一个线程操作的时候,其他的线程不会同时操作,因此不会存在二义性问题

那么为什么 ConcurrentHashMap 源码不设计成可以判断是否存在 null 值的 key?

如果 key 为 null,那么就会带来很多不必要的麻烦和开销。比如,你需要用额外的数据结构或者标志位来记录哪些 key 是 null 的,而且在多线程环境下,还要保证对这些额外的数据结构或者标志位的操作也是线程安全的。而且,key 为 null 的意义也不大,因为它并不能表示任何有用的信息。

4、如果多线程同时操作一个数据,会有什么问题,怎么解决?

会存在线程安全的问题,只需要控制多个线程之间的操作同步,并且对该变量添加 volatile 关键字,保证该变量对多个线程的可见性即可

控制多个线程之间操作同步的话,通过 synchronized 或者 ReentrantLock 进行控制即可

5、线程池介绍一下,线程池的参数中最大线程数可以设得比核心线程数小吗?

介绍线程池的时候,说一下线程池的几个核心参数,以及线程池的工作流程

线程池中重要的参数如下:

  • corePoolSize :核心线程数量
  • maximumPoolSize :线程池最大线程数量 = 核心线程数+非核心线程数
  • keepAliveTime :非核心线程存活时间
  • unit:空闲线程存活时间单位(keepAliveTime单位)
  • workQueue :工作队列(任务队列),存放等待执行的任务
    • LinkedBlockingQueue:无界的阻塞队列,最大长度为 Integer.MAX_VALUE
    • ArrayBlockingQueue:基于数组的有界阻塞队列,按FIFO排序
    • SynchronousQueue:同步队列,不存储元素,对于提交的任务,如果有空闲线程,则使用空闲线程来处理;否则新建一个线程来处理任务
    • PriorityBlockingQueue:具有优先级的无界阻塞队列,优先级通过参数Comparator实现。
  • threadFactory :线程工厂,创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等等。
  • handler: 拒绝策略 ,有4种
    • AbortPolicy :直接抛出异常,默认策略
    • CallerRunsPolicy:用调用者所在的线程来执行任务
    • DiscardOldestPolicy:丢弃阻塞队列里最老的任务,也就是队列里靠前的任务
    • DiscardPolicy :当前任务直接丢弃

新加入一个任务,线程池处理流程如下:

  1. 如果核心线程数量未达到,创建核心线程执行
  2. 如果当前运行线程数量已经达到核心线程数量,查看任务队列是否已满
  3. 如果任务队列未满,将任务放到任务队列
  4. 如果任务队列已满,看最大线程数是否达到,如果未达到,就新建非核心线程处理
  5. 如果当前运行线程数量未达到最大线程数,则创建非核心线程执行
  6. 如果当前运行线程数量达到最大线程数,根据拒绝策略处理
image-20240227123406636
image-20240227123406636

线程池的参数中最大线程数可以设得比核心线程数小吗?

这个一般对于线程池有了解的都不会这么设置,最大线程数 = 核心线程数 +非核心线程数,所以最大线程数不可能比核心线程数还要小,这是错误的使用方式

JVM

6、JVM 内存结构

JVM 的内存结构分为:堆、虚拟机栈、本地方法栈、方法区

主要存储 JVM 中创建的对象,堆是多个线程共享的空间

方法区 主要存储编译后的 Java 代码,也就是 class 文件的信息

虚拟机栈 包括了一个个的栈帧,每执行一个方法,都会为该方法生成一个栈帧压入虚拟机栈中,当执行完该方法之后,就会将该栈帧弹出虚拟机栈,这个虚拟机栈是 线程私有 的,方法中的一些局部变量也会在该栈帧中进行存储

本地方法栈 类似于虚拟机栈,里边的栈帧就是使用到的本地方法,本地方法指的是底层的非 Java 代码,因为 Java是一门高级语言,我们不直接与操作系统资源、系统硬件打交道。如果想要直接与操作系统与硬件打交道,就需要使用到本地方法了

程序计数器 用于存储当前线程所执行的字节码指令的行号,让线程知道下一次要执行哪一个字节码指令,程序计数器是线程私有的

JVM 整体结构图如下:

JVM 架构
JVM 架构

7、垃圾回收算法和垃圾回收器都讲一下

垃圾回收算法有:标记-清除算法、复制算法、标记-压缩算法、分代回收算法

标记-清除算法 会从 GC Roots 开始遍历,将可到达的对象做标记,标记为存活对象,那么其他未标记的对象就是需要对象,将垃圾对象清除掉即可

缺点就是会产生内存碎片

复制算法 需要将内存区域分成大小相等的两块,当需要 GC 时,将其中一块内存区域中的存活对象复制到另外一块区域,再将原来的一块内存区域清空即可

优点是不会产生内存碎片,缺点是存在比较大的空间浪费

标记-压缩算法 是基于标记-清除算法的改进,先标记存活对象,之后将所有存活对象压缩到内存的一端,清除边界以外的垃圾对象即可

优点是既解决了标记-清除算法出现内存碎片的问题,又解决了复制算法中空间浪费的问题,但是效率低于复制算法

分代收集算法 是将 Java 堆分为新生代和老年代,这样就可以对不同生命周期的对象采取不同的收集方式,因为新生代中的对象生命周期短,存活率低,适合使用 复制算法 ,老年代生命周期长,存活率高,适合使用 标记-清除标记-压缩 算法

垃圾收集器

有 8 种垃圾回收器,分别用于不同分代的垃圾回收:

  • 新生代回收器:Serial、ParNew、Parallel Scavenge
  • 老年代回收器:Serial Old、Parallel Old、CMS
  • 整堆回收器:G1、ZGC

这里就不重复介绍了,可以参考 :JVM垃圾收集器

JDK1.8 中默认的垃圾收集器是 Parallel Scavenge(新生代)+Parallel Old(老年代)

公司中一般使用指定 G1 作为垃圾收集器的比较多 ,因为 G1 的特点就是天生适合用于大内存机器,无论内存多大,都可以指定期望的 GC 停顿时间,这样不至于停顿时间太长,导致用户体验卡顿

8、有看过 GC 日志吗

GC 日志的话可以通过 gceasy 工具进行分析,首先需要设置 VM Options 来开启 GC 日志打印:

 # 开启 GC 日志创建更详细的 GC 日志
 -XX:+PrintGCDetails 
 # 开启 GC 时间提示
-XX:+PrintGCTimeStamps,-XX:+PrintGCDateStamps
# 打印堆的GC日志
-XX:+PrintHeapAtGC 
# 指定GC日志路径
-Xloggc:./logs/gc.log

分析 GC 日志的话,就是将生成的 gc.log 日志文件放入 gceasy 工具进行分析,分析的话主要看以下这几个重要的参数:

1、新生代、老年代、元空间占用情况: 看一下分配的空间大小以及峰值空间大小,来判断是否空间分配不合理,在 JDK1.8 中,如果不指定元空间大小,默认的初始值为 21MB,最大值为系统内存大小,元空间太小会导致频繁 Full GC 来提升元空间大小,因此这一点要注意

2、平均/最大 GC 暂停时间: 看一下暂停时间有没有特别长,如果特别长,说明是存在问题的

3、GC 持续时间/GC 次数: 判断 GC 持续时间是否过长、GC 次数是否频繁,如果 Full GC 较为频繁,也是存在问题的(因为 Full GC 比较慢,要减少 Full GC 次数),之后就要分析 Full GC 原因,看看是有大对象、还是产生非常多的对象、还是元空间初始值太小了

详细 GC 日志分析可参考:通过 gceasy工具对生成的 GC 日志进行分析

MQ

9、项目中的 RocketMQ 怎么保证消息一定发出去且收到了?

这里问的就是 RocketMQ 如何保证消息的可靠性,避免消息在传输过程中丢失了

RocketMQ 作为分布式消息中间件,肯定是要尽可能保证消息传输的 可靠性 ,要保证消息的可靠性,先来思考一下从哪些方面保证呢?

这要看消息的生命周期,既然保证可靠性,那么就是要保证 A 发送给 B 的消息一定可以成功,那么首先要保证发送成功,其次要保证 B 接收成功,而在 RocketMQ 中,消息是先发送到 Broker 中了,那么还需要保证 MQ 在 Broker 中不会丢失

因此 RocketMQ 是从三方面保障了消息的可靠性:

  • 保证 生产者发送消息 的可靠性
  • 保证 Broker 存储消息 的可靠性
  • 保证 消费者消费消息 的可靠性
发送消息的可靠性

RocketMQ 在发送端保证发送消息的可靠性主要就是通过 重试机制 来实现的

生产者发送消息分为了 同步发送异步发送单向发送 三种方式:

  • 同步发送 :发送消息后,阻塞线程等待消息发送结果
  • 异步发送 :发送消息后,并不会阻塞等待,回调任务会在另一个线程中执行
  • 单向发送 :发送消息后,立即返回,不返回消息发送是否成功,因此不可以保证发送消息的可靠性

只有单向发送没有消息可靠性的保证,在 同步异步 发送中,都可以通过设置发送消息的 重试次数 来保证发送端的可靠性,默认重试次数为 2 次

并且还可以设置如果发送失败,尝试发送到其他 Broker 节点

// 同步设置重试次数
producer.setRetryTimesWhenSendFailed(3)
// 异步设置重试次数
producer.setRetryTimesWhenSendAsyncFailed(3);
// 如果发送失败,是否尝试发送到其他 Broker 节点
producer.setRetryAnotherBrokerWhenNotStoreOK(true);
存储消息的可靠性

可靠性保证一:消息落盘存储保证消息的可靠性

在消息发送到 Broker 之后,Broker 会将消息存储在磁盘中,这样如果 Broker 异常宕机之后,可以读取磁盘中的数据来保证消息的 可靠性

RocketMQ 如何存储消息:

RocketMQ 会先将消息写入到操作系统的 page cache 中,之后消息刷入磁盘分为了 同步刷盘异步刷盘 两种方式, 默认是异步刷盘方式

page cache 就是将文件映射到内存中,这样直接操作内存比较快,避免了频繁的磁盘 IO

Broker 通过 page cache异步刷盘 在保证消息可靠性的前提下,还尽可能提升了消息写入的性能

在 Broker 端写入消息的流程如下:

image-20240325151146744
image-20240325151146744

可以看到,这里写消息先写在了 JVM 的 堆外内存 中,而不是直接写在了 page cache 中,这是 RocketMQ 提供的 transientStorePoolEnabled(瞬时存储池启用)机制 来实现内存级别的读写分离(需要开启 transientStorePoolEnabled(瞬时存储池启用)机制 才会先写入 JVM 的堆外内存)

为什么要将消息先写在 堆外内存 呢?如果高并发的读写请求都直接落在 page cache 中的话,那么会导致对 page cache 的竞争太过于激烈,因此令写请求操作 堆外内存 ,读请求操作 page cache ,实现 读写分离 ,避免高并发情况下对 page cache 的激烈竞争

可靠性保证二:主从复制保证 Broker 的消息可靠性

上边是通过将消息写入磁盘来保证 Broker 存储端的消息可靠性,还有另一种方式:对 Broker 采用一主多从的方式部署,通过 主从复制 来保证消息的可靠性

在 Broker 主从复制时,会将 master 节点的消息同步到 slave 节点,slave 节点作为 master 节点的 热备份 存在,保证消息的可靠性

消费消息的可靠性

消费者为了保证消息的可靠性: 会先消费消息,再提交消息消费成功的状态 ,不过可能会出现 重复消费 的情况,因此需要业务方保证 幂等性 来解决重复消费的问题(可以建立一张消息消费表来避免重复消费)

可靠性保证一:消息重试保证可靠性

消费者只有返回 CONSUME_SUCCESS 才算消费完成,如果返回 CONSUME_LATER 则会按照不同的延迟时间再次消费,如果消费满 16 次之后还是未能消费成功,则会将消息发送到死信队列

可靠性保证二:死信队列保证可靠性

如果消息最终重试消费失败,并不会立即丢弃,而是将消息放入到了死信队列,之后还可以通过 MQ 提供的接口获取对应的消息, 保证消费消息的可靠性

本文由 mdnice 多平台发布

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

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

相关文章

Stable Diffusion绘画 | 插件-Addition Networks:单独控制LoRA

当 SD 使用到了进阶阶段,经常需要添加多个 LoRA 来生成图片,因此,提示词中难免会出现一系列的 LoRA 和相关触发词。 但很多时候,我们直接复制网上别人分享的完整提示词,会发现生成出来的效果不一样,这是怎么…

【嵌入式】嵌入式系统和图形用户界面(GUI)开发的图形库和框架

目录 1. **LVGL (Light and Versatile Graphics Library)**2. **TouchGFX**3. **EmWin**4. **Qt for Embedded**5. **SDL (Simple DirectMedia Layer)**6. **Nano-X**7. **Cairo**8. **GTK**9. **Allegro**10. **Qt Quick (QML)**11. **GUIX**12. **FLTK (Fast, Light Toolkit)…

Solidity智能合约中的异常处理(error、require 和 assert)

Solidity 中的三种抛出异常方法:error、require 和 assert 在 Solidity 开发中,异常处理是确保智能合约安全性和正确性的关键步骤。Solidity 提供了三种主要方法来抛出异常:error、require 和 assert。本文将详细介绍这三种方法的用途、实现方…

心觉:如何重塑高效学习的潜意识(2)明白你为什么这么学,才能学得更好

Hi,我是心觉,与你一起玩转潜意识、脑波音乐和吸引力法则,轻松掌控自己的人生! 挑战每日一省写作181/1000天 上一篇文章我们讲了系统化学习和边学边用两种方法的优缺点 为什么有些人喜欢这种而不是那种 他们的底层心理逻辑不一…

智能识别猫猫

鸡蛋饼是什么猫 今天,有一位爱猫人士找到了我:“9月25日啦,炉石传说重新开服了!” 我:“哦!我知道这个,你是说,我现在该去领金卡了吗?” 爱猫人士:“不&am…

VMware下Ubuntu找不到共享文件夹

在VMware的设置中已经设置了共享文件夹,在Ubuntu系统中找不到,参考了网上其他的文章,发现还是不能解决问题,无意中尝试了一小步,没想到成功解决了,在这里记录一下。 1)首先查询本机的gid 2&…

聚焦Llama新场景和AR眼镜,扎克伯格用AI赋能元宇宙,Meta Connect 2024开发者大会直播约起...

作者:十九 编辑:十九,李宝珠 北京时间 9 月 26 日凌晨 1 点,Meta Connect 2024 开发者大会即将举行,马克扎克伯格将聚焦 AI 和元宇宙,向大家分享 Llama 模型的更多潜在应用,并介绍 Meta 最新产品…

2024年汉字小达人区级自由报名备考冲刺:最新问题和官模题练一练

今天是2024年第十一届汉字小达人的区级自由报名活动的第二天。 我们继续回答几个关于汉字小达人的最新问题,做几道2024年官方模拟题,帮助孩子们少走弯路,再冲刺一般,更精准地备考2024年汉字小达人。 【温馨提示】本专题在比赛期…

芯科科技2024年Works With开发者大会登陆上海,物联网和人工智能的变革性融合带来无限精彩

谷歌、三星等生态大厂将带来重磅演讲和圆桌讨论,亦可切身体验多样化无线技术实作 中国,北京 – 2024年9月25日 – 安全、智能无线连接技术领域的全球领导厂商Silicon Labs(亦称“芯科科技”,NASDAQ:SLAB)&a…

MySQL InnoDB MVCC读写逻辑分析与调测

目标 1、构建MVCC读写场景 2、gdb调试MVCC过程,输出流程图(函数级别调用过程) 前提 准备1 打开服务端 查询mysqld进程号 线程树 打开客户端,想创建几个事务号就打开几个客户端 准备2 数据库mvcc,两个表test和stu…

JVM(HotSpot):虚拟机栈(JVM Stacks)之线程问题排查方法

文章目录 前言一、CPU占用过大二、程序运行很长时间没有结果三、总结 前言 本篇讲的排查都是基于Linux环境的。 一、CPU占用过大 这个一般是出现了死循环导致的。 1、先用top命令查看占用CPU的进程ID top2、再用ps命令查看对应的线程 就看一查看到对应的线程id ps H -eo …

王道考研视频——操作系统笔记

操作系统第一章!入门 王道考研视频——操作系统笔记,第一部分,操作系统的概念和体系结构 0.0 课程白嫖指南_哔哩哔哩_bilibili0.0 课程白嫖指南是王道计算机考研 操作系统的第1集视频,该合集共计84集,视频收藏或关注UP…

openkylin介绍及其特点和优势

openKylin(开放麒麟)openKylin(开放麒麟) 社区是在开源、自愿、平等和协作的基础上,由基础软硬件企业、非营利性组织、社团组织、高等院校、科研机构和个人开发者共同创立的一个开源社区,致力于通过开源、开…

51单片机应用开发---keil 创建一个新工程并用Protues 8仿真(以点亮LED为例)

实现目标 1、掌握keil V5软件 创建一个新工程; 2、具体目标:1.会新建一个工程;2.编程实现点亮开发板的LED1. 一、新建工程步骤 1.1 在桌面上新建一个名字为 LED的文件夹 1.2 双击打开Keil uVision5 软件,点击 Project —>…

HTML和CSS中的浮动以及边框塌陷解决方案(内置练习及答案)

一、浮动概述 在HTML和CSS中,“浮动”(Float)是一种布局技术,它允许元素脱离其正常的文档流,向左或向右移动,直到它的外边缘碰到包含框或另一个浮动元素的边缘。浮动元素仍然保持块级盒模型的特性&#xff…

【GUI设计】基于图像分割的GUI系统(6),matlab实现

博主简介: 如需获取设计的完整源代码或者有matlab图像代码项目需求/合作,可联系主页个人简介提供的联系方式或者文末的二维码。博客内容有疑问可联系沟通(博主邮箱:3249726188qq.com)。 ~~~~~~~~~~~~~~~~~~~~~~~…

【ComfyUI】减少连线的节点——cg-use-everywhere

源码:https://github.com/chrisgoringe/cg-use-everywhere 介绍:一组节点,允许数据“广播”到一些或所有未连接的输入端。大大减少了链接混乱。 【秋葉aaaki】comfyui一键运行包 夸克网盘:https://pan.quark.cn/s/64b808baa960 …

PMP--二模--解题--131-140

文章目录 反例14.敏捷–角色–教练/项目经理–仆人式领导–职责–核心工作–消除障碍;–作用–促进合作(关键字:合作,一起解决问题)--不是出现“合作”就一定选131、 [单选] 一个项目经理被分配到一个针对客户的分析项…

【网络安全】网络基础第一阶段——第三节:网络协议基础---- VLAN、Trunk与三层交换技术

目录 一、交换机 1.1 交换机定义 1.1.1 交换机 1.2 工作原理 1.2.1 数据帧的转发 1.2.2 交换机处理数据帧的三种行为 1.2.3 交换机通信 二、虚拟局域网(VLAN) 2.1 虚拟局域网简介 2.1.1 为什么需要VLAN 2.1.2 广播域的分割与VLAN的必要性 2.…

【Linux】权限管理——专治不会设置权限而头疼

🚀个人主页:小羊 🚀所属专栏:Linux 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 前言一、Linux权限管理1.1 Linux用户类型1.2 文件类型和访问权限1.3 文件访问权限的相关设置方法1.3.1 更改文…