JAVA面试题2024最新版

1. JDK 和 JRE 和 JVM 分别是什么,它们之间有什么区别?

  1. java程序如何在计算机上面运行:

    • 编写java源码; 【需要使用到jdk java开发工具包】
    • 将源码编译为字节码; 【需要用到java开发工具包里面的编译器javac.exe生成.class文件】
    • java虚拟机(JVM)将字节码转为机器码; 【需要用到java虚拟机】
    • 操作系统执行机器码完成程序的运行; 【需要用到java运行环境】
  2. 区别:

    1. JDK (java开发工具包) 开发java程序所需要的文件包
    2. JRE(java运行环境) 运行java程序所需要的文件包
    3. JVM(java虚拟机) 运行java代码的虚拟机(不同操作系统的jvm是不一样的,且可以自己创建一个属于自己的jvm)
      【JDK > JRE > JVM】
  3. 总结:

    1. java开发工具包 = java运行环境 + java开发工具
    2. java运行环境 = java虚拟机 + java核心类库

2.什么是字节码?采用字节码的好处是什么?

  1. 字节码是java开发工具包里面的编译器javac.exe编译之后生成的.class文件。
  2. 好处:
    • 可移植性: 可以在任何支持jvm的平台上运行
    • 安全性: 字节码在jvm中可以进行安全检查,可确保系统不会造成病毒
    • 性能:二进制格式,相较于jvm编译之后的机器码,可以更快的传输和加载
    • 性能:字节码有更好的可读性,方便的进行反汇编和调试

3.什么是数据库事务(ACID)?讲一下事务的特性?

  1. 数据库事务时只数据库的一组数据库操作,该操作可以看作一个整体是阻塞同步的,操作要么都执行,要么都不执行(失败回滚)。
  2. 特性:
    • 原子性: 是一个不可分割的原子操作,只要其中一个操作失败整个事务就会被回滚到原始状态 【应用场景:如果一个方法里面涉及到了对两个表的数据操作或者是多次多表的操作就可以在方法上面加上注解 @Transactional(rollbackFor = Exception.class) 就行
    • 一致性: 事务执行结束后的数据必须保持一致性,数据库必须满足一定的规则,比如说唯一性约束,引用完整性等
    • 隔离性: 事务执行过程中,不应该受到其他事务的影响,事务之间隔离,互不干扰
    • 持久性:事务一旦执行完成提交之后,其对信息的修改必须永久保存到数据库中,即使系统发生故障,数据也不会改变

4. 什么是 Redis?Redis 有哪些特点?Redis 有哪些常见的应用场景?

Redis是一个高性能的键值对存储系统。(NoSQL)

  1. 特点:
    • 读写性能优:存储在内存中
    • 支持多种数据结构:string,hash,set等
    • 分布式:可以作为分布式存储,提高可用性
    • 指令丰富:有丰富的指令来实现分布式锁,缓存等功能
  2. 应用场景:
    • 缓存:作为缓存使用,提升数据的读写速度
    • 消息队列:提供了列表和发布/订阅功能
    • 计数器:实现页面的访问量,点击量等计数
    • 排行榜:有序集合功能可以用来实现排行榜
    • 分布式锁:可以用来实现分布式锁,保证多个进程之间互斥访问
  3. 自己项目的应用:
    • 避免用户恶意加入队伍的请求,使用分布式锁来防止用户加入的数量(前端也可以使用防抖和节流来实现)
    • 将用户的登录态存储到redis中实现单点登录
    • 加快首页的响应速度,设置定时任务将数据缓存到redis中(一定要设置过期时间)

5. 计算机网络七层模型和各自的作用?

浏览器输入网址访问网站时的整个流程:首先经过物理层将电信号转为比特流,接着通过数据链路层将比特流转为数据帧,通过MAC地址寻找下一跳设备进行传输。然后在网络层中通过IP地址寻找目标主机,路由器选择最优路径进行数据传输。接着在传输层中通过TCP协议保证数据传输的可靠性,同时控制数据流量。最后在应用层中通过HTTP协议实现浏览器和服务器之间的通信,用户才能看到最终的网页展示效果。

  1. 七层模型(应表会传网数物)
    • 应用层:提供用户接口能够与网络进行交互联系
    • 表示层:对来自应用层的数据进行解释,并按照一定格式传递给会话层
    • 会话层:允许两个实体之间建立和维持会话,并支持数据交换
    • 传输层:下面三层负责数据通信,上面三层负责数据处理,该层提供建立和维护传输连接的功能
    • 网络层:主要解决不同子网间的通信
    • 数据链路层:通过差错控制,流量控制方法,将有差错的物理线路变为无差错的数据链路
    • 物理层: 利用传输介质实现相邻计算机结点间的比特流透明传送

6. JDK 动态代理和 CGLIB 动态代理的区别是什么?

  1. JDK 动态代理的原理(spring默认)

    • 通过java的反射机制来实现的,只能代理实现了接口的类。
    • jdk动态代理会创建一个实现了代理接口的代理类,在代理方法被调用时,invocationhandler对象会被回调来执行代理的逻辑
    • 是一种面向接口的代理模式,没有接口就不能实现
  2. CGLIB动态代理的原理

    • 通过字节码技术实现,可以代理那些没有实现接口的类。CGLIB动态代理会生成一个被代理类的子类,并重写被代理类的所有非final方法,在代理方法被调用时,MethodInterceptor对象会被回调来执行代理逻辑
  3. 总结:

    jdk动态代理适用于代理实现了接口的类,基于java反射机制实现。CGLIB动态代理适用于代理没有实现接口的类,基于字节码技术实现。

  4. 使用场景:

    • AOP: 面向切面编程中,常常需要在方法的前后执行一些操作,比如打印日志,性能监控等
    • RPC框架

7.Spring 框架是什么?使用 Spring 框架有哪些好处?

  1. Spring 框架是什么:

    是一个开源的java企业应用程序框架,通过依赖注入和面向切面编程等技术为开发者提供了一个全面的配置模型,降低了java开发的复杂度,提高了代码的维护性。

  2. 使用 Spring 框架有哪些好处:

    • 方便解耦,简化开发: spring就是一个大工厂,可以将所有对象的创建和依赖关系的维护交给spring管理
    • 方便集成各种优秀框架:内部提供了对各种优秀框架的支持,mybatis
    • 降低了java EE 中api的使用难度
    • 方便进行单元测试
    • AOP编程支持:spring提供面向切面编程,可以方便的实现对程序的权限拦截打印日志、运行监控等功能
    • 支持声明式事务管理:通过配置就可以管理应用中的事务,简化了事务管理的过程

8. 讲解以下Redis的单线程模型是什么还有IO多路复用是什么?

  1. 单线程模型:
    • Redis是一款基于内存的高性能键值对存储系统,采用的是单线程模型的设计
    • 所有的客户端请求都是由一个单线程来处理,该线程不断地读取客户端的请求命令,并放入一个队列,然后Redis的事件处理器会按照一定的规则选择其中的某个请求进行处理,将结果返回给客户端
    • 优点:可以很好的避免多线程引发的高并发和死锁的问题,简化了系统设计;由于数据是存储于内存所以也能保证单线程处理请求的性能
  2. IO多路复用:
    • 在一个线程中同时监听多个文件描述符,一旦准备就绪就处理对应的事件
    • Redis采用的就是epoll的IO多路复用技术,可以实现高效的事件监听和响应

总结:Redis中客户端的请求是由一个单线程来处理的,IO操作又是由多路复用来实现的,这种设计充分的利用了CPU的性能,又保证了IO的运算力,从而实现了高效的键值存储服务

9.Redis基础类中的String底层实现是什么?

  1. 底层实现:
    • 底层实现是一个简单动态字符串,也就是字符串动态增长实现的一种方式
  2. SDS(简单动态字符串)特点:
    • 对内存的分配和释放进行了封装,使得字符串可以根据需要进行增长或者缩减
    • 记录了分配给字符串空间的长度,可以方便的计算出是否需要扩容
    • 使用了惰性空间释放,不会在空间缩减时立即释放空间,而是等到需要扩容时再重新分配内存
    • 提供了字符串追加操作,可以在o(1)的时间内完成

10. 如何使用Redis实现一个排行榜?

  1. 步骤:

    • 使用有序集合来存储排行榜的数据,将用户得分作为分数,用户ID作为成员,当用户得分改变时使用ZADD命令将分数更新到集合中
    • 获取排行使用ZREVERANGE命令按照倒序获取集合中的数据
    • 获取某个用户的分数使用ZSCORE命令
    • 获取某个用户排名使用ZREVERANK命令
  2. Java代码实现:

    // 添加学⽣的成绩
    // redisTemplate表示redis操作对象
    public void addScore(String name, int score) {
     redisTemplate.opsForZSet().add("scores", name, score);
    }
    
    // 查询排名前N的学⽣成绩  
    public List<Map.Entry<String, Double>> getTopScores(int n) {
     return redisTemplate.opsForZSet().reverseRangeWithScores("scores",
    0, n - 1)
     .stream()
     .map(tuple -> new AbstractMap.SimpleEntry<>
    (tuple.getValue(), tuple.getScore()))
     .collect(Collectors.toList());
    }
    
    // 删除某个学⽣的成绩
    public void removeScore(String name) {
     redisTemplate.opsForZSet().remove("scores", name);
    }
    

11. Redis的持久化机制有那些,它们之间的区别是:

  1. 有哪些:
    • RDB
    • AOF
  2. 区别:
    • RDB:
      • 在指定的时间间隔队数据集做快照存储到磁盘中
      • 优缺点:对于数据恢复速度比较快,但存储的数据量比AOF小;如果快照的时间间隔长的话就可能出现数据丢失的情况
    • AOF:
      • 将每一次的写操作都追加到AOF文件中(即使断电重启也能根据该文件重建数据集)
      • 优缺点:数据丢失可能性较低,文件比RDB大,数据恢复速度较慢
  3. RDB+AOF混合使用:
    1. 使用混合持久化机制,以此来取长补短
    2. 在混合持久化机制中,AOF保存每次写操作,RDB保存指定时间点的数据快照,以此来达到数据恢复速度和数据完整性的平衡。
  4. 应用场景:
    • AOF 适合数据集比较小,数据完整性比较重要的场景,比如金融,电商
    • RDB 适合数据集比较大,数据恢复速度较快的场景,比如备份,灾难恢复

12. 如何在Redis中实现分布式session

  1. 单机登录:

    1. 服务器创建session并分配一个唯一ID

    2. 响应时创建一个cookie用于存储该sessin ID

    3. 客户端收到cookie后就会自动保存这个session ID

    4. 在下次访问时就会自动带上该session ID 服务器就进行判断是否与自身的session ID一致来识别用户身份

    image-20240228223150150

总结:上面的登录方式存在的不足:现在的应用大都是用两台及以上的服务器进行部署,所以单机登录只能在当前服务器上面获取用户信息session是没有共享的,就存在了session同步的问题

  1. 分布式登录:

    1. 用户登录成功之后将session存储在Redis中并设置唯一的key值

    2. 客户端返回响应的同时将session ID以cookie 的形式返回给客户端

    3. 在后续的请求中服务器会根据从客户端传递过来的Cookie获取Session ID,然后根据这个ID从Redis中获取对应的Session数据,如果没有找到就无法通过认证

    4. 用户退出登录或者session失效时需要将redis中的session数据清空,可以使用expire命令设置session的过期时间自动删除

    image-20240228224123590

13. Redis的内存淘汰机制和策略有那些?

  1. 淘汰机制
    • 定期删除:设置一个定时器,定期扫描空间中的键,并删除已经过期的键
    • 惰性删除:一个键过期不会立即删除,等到被再次访问时删除
    • 内存淘汰策略:当内存占用达到上限,会根据内存淘汰策略来进行键的删除,腾出内存空间
  2. Redis的内存淘汰策略
    • noeviction: 不删除键,返回错误
    • allkeys-lru: 删除最近最少使用的键
    • volatitle-lru: 删除设置了过期时间并且最近最少使用的键
    • allkeys-random: 随机删除键
    • volatitle-random: 随机删除设置了过期时间的键
    • volatitle-ttl: 删除设置了过期时间并且剩余生存时间最短的键
  3. 如何设置内存淘汰策略
    • 配置文件中找到maxmemory和maxmemory-policy两个参数
    • 前一个设置内存限制,后一个设置内存淘汰策略

14. Redis 6.0 之后为何引入了多线程? 6.0之前为什么不能使用多线程?

  1. 原因:

    6x之前Redis的性能瓶颈主要体现在CPU上,随着硬件的发展cpu的核数已经多达几十个,这就导致Redis的单线程模型无法充分利用多核处理器的性能,所以引入了多线程。

  2. 不使用多线程的原因:

    • 单线程模型相对简单,容易维护和调试
    • redis的瓶颈在于CPU不是I/O,因此采用多线程模型并不能提高性能
    • 内存型数据库,性能主要受到CPU和内存带宽的限制,采用多线程模型会增加线程之间的竞争开销,反而可能降低其性能
  3. 总结:

    随着硬件的发展,多核处理器已经成为了现代服务器的标配,因此引入Redis多线程的举措可以更好地发挥硬件的性能,提高响应速度和吞吐量

15. Redis为什么这么快?

  1. 内存存储:数据存储于内存中,相比于存储在磁盘中肯定运算速度更快
  2. 单线程模型:使用单线程进行请求的处理,相比多线程少了资源的竞争和切换等开销,提高了处理请求的效率
  3. 非阻塞I/O:非阻塞I/O通信,当一个请求到来时,如果出现了问题,redis不会一直等待,而是会先处理其他的请求
  4. 精简高效的数据结构:内置多种高效的数据结构,比如hash,跳表等,减少了redis对内存和cpu的占用,从而提高了redis的性能
    1. 持久化策略:支持多种持久化策略,比如RDB和AOF等,这些策略可以将内存数据保存到硬盘中,保证了数据的持久性和完整性。同时redis将数据以压缩的方式存储在硬盘中,减少了硬盘的占用,提高了读写速度。

16. Redis有那些数据类型?基础数据结构有哪几种?还有那些高级的数据结构?

  1. 基础数据结构
    • String: 最基本的数据类型,可以存储任何形式的数据
    • Hash:键值对类型,可以存储多个键值对,每一个键值对又是一个键值对结构
    • List:有序列表类型,可以存储多个元素
    • Set:无序集合类型,每个元素都是唯一的
    • Sorted Set: 有序集合,每个元素都有一个分支,可以根据分值进行排序和查询操作
  2. 高级数据结构
    • HyperLogLog: 基数估计算法,用于估计一个数据集合的基数
    • GeoHash:地理位置编码算法,可以根据地理位置信息进行编码和查询
    • Pub/Sub:消息队列机制,可以实现消息的订阅和发布
    • Bitmaps:图数据结构,可以进行高效的位运算,用于统计用户在线时长,网站访问量
    • Lua脚本:可以使用lua脚本进行定制扩展,实现一些复杂的业务场景
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值