第一天

1.JDK、JRE、JVM分别是什么,有什么区别

JDK包含JRE,JRE又包含JVM。

JDK:Java语言的开发工具包

JRE:Java Runtime Environment,Java运行时环境,包含JVM标准实现及Java核心类库

JVM:Java Virtual Machine,java虚拟机,它是虚构出来的计算机,是实现java跨平台的法宝

2.字节码是什么,采用字节码最大的好处是什么

字节码:Java源代码经过虚拟机编译器编译后产生的文件(即扩展为.class的文件)

好处:Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以Java程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。

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

数据库事务:是指一个操作序列,包含一组数据库操作命令,这些命令视为一个整体,要么同时成功,要不都不执行

ACID特性:

原子性:事务是最小单元,不可再分

一致性:事务中的所有命令要么同时成功,要么同时失败

隔离性:事务与事务之间相互隔离,互不影响

持久性:事务对数据的改变应该是持久的

第二天

1.Java 和 C++、Go 语言的区别,各自的优缺点?

  1. java

    优点:跨平台可移植、面向对象、高性能、分布式

    缺点:删除了指针,不像C++那样灵活;依靠java虚拟机,不能和底层打交道;运行速度相对较慢

  2. C++

    优点:在C的基础上增加面向对象的特点,代码可读性好,运行效率高;性能好,复用性强

    缺点:相对于JAVA来说,没有垃圾回收机制,容易引发内存泄露

  3. go

    优点:丰富的标准库;标准化的测试框架

    缺点:没有枚举;依赖管理

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

  1. Redis是一个基于内存的k-v数据库,C语言开发,可以用来作为数据库、缓存和消息队列

  2. 特点

    • 高性能:写的速度达到11万次每秒,读8.1万次
    • 持久化
    • 主从复制
    • 支持众多语言
  3. 应用场景:以社交平台为例

    string

    场景一:缓存热点数据,具体热点帖子的缓存

    场景二:计数器,缓存用户的关注数和粉丝数、限流

    场景三:分布式锁,利用setnx指令

    list

    场景一:缓存热点数据,热点列表,高粉的内容列表或者首页的热点内容列表

    场景二:消息队列,不怕数据丢失的消息,帖子点赞消息提醒

    set

    场景:利用set的不重复属性加Redis可以对set求交集并集,可以做共同好友,个人标签和文章标签(求交集精准推送)

    sort set

    场景:有序set,粉丝观看时间数排序,点赞量排序

    hash

    场景:缓存对象时比如用户资料,可以转成json当字符串存,也可以把属性转成hash表存

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

OSI七层模型

第三天

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

JDK动态代理是java自身的,它是基于接口的动态代理。原理是反射

cglib是第三方工具库,基于类实现,原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强

  1. jdk动态代理的实现过程

    • 创建类实现接口InvocationHandler
    • 重写invoke()方法,在invoke方法中完成目标方法的调用
    • 使用时创建代理对象,用Proxy的newProxyInstance创建代理对象,代理对象调用方法

2.MySQL 日志有了解过吗?binlog、redolog、undolog 分别有什么作用?

  1. binlog是二进制日志,记录内容是语句的原始逻辑,不管用什么存储引擎,只要发生了表数据更新,都会产生 binlog 日志。
  2. redolog是重做日志,是InnoDB存储引擎独有的,它让MySQL拥有了崩溃恢复能力。比如 MySQL 实例挂了或宕机了,重启时,InnoDB存储引擎会使用redo log恢复数据,保证数据的持久性与完整性。
  3. undolog是回滚日志,所有事务进行的修改都会先记录到这个回滚日志中,然后再执行相关的操作。如果执行过程中遇到异常的话,我们直接利用回滚日志中的信息将数据回滚到修改之前的样子即可。

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

Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。

从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

Spring为简化开发而生,让程序员只需关注核心业务的实现,尽可能的不再关注非业务逻辑代码(事务控制,安全日志等)。

第四天

1.Java 中 final 关键字有什么用?

final是最终的意思

  • 类前加final:该类不可被继承
  • 方法前加final:不能被覆盖
  • 变量前加final:只能被赋值一次
  • 与static联合修饰的变量称为常量

2.HTTP 是哪一层的协议?简述它的作用?

http,即超文本传输协议,属于应用层,是基于应用层(TCP/IP参考模型)的通信规范;是从Web服务器传输超文本到客户端的传输协议,无状态的传输协议;不仅能够保证正确、快速、高效的传输超文本文档,而且可以确定资源加载顺序等。

3.什么是进程和线程?它们有哪些区别和联系?

线程是进程划分成的更小的运行单位,一个进程在其执行的过程中可以产生多个线程。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。线程执行开销小,但不利于资源的管理和保护;而进程正相反。

第五天

1.Java 中 hashCode 和 equals 方法是什么?它们和 == 各有什么区别?

hashcode返回对象的哈希码值,equals判断两个对象是否相等。

equals方法是属于object类当中的,通过阅读源码,我们能发现,方法的底层就是用的双等号,所以在没重写之前,对于基本数据类型比较的是本身的值,而对象则比较的是内存地址,但是在实际业务中,我们希望的是通过equals方法比较两个对象的内容是否相等,所以一般要重写equals

2.Spring 的两大核心概念是什么?简单讲一下你对它们的理解

IOC

即控制反转,将对象的创建交给容器管理。

怎么理解:假设我们的业务中有一个UserDaoImplForMySQL接口实现类,主要是连接MySQL数据库进行操作。如果更换到Oracle数据库上,则需要再提供一个UserDaoImplForOracle接口实现类。以上的操作正在进行功能的扩展,添加了一个新的类UserDaoImplForOracle来应付数据库的变化,这里的变化会引起连锁反应吗?当然会,如果想要切换到Oracle数据库上,UserServiceImpl类代码就需要修改,如下:

//private UserDao userDao = new UserDaoImplForMySQL();
private UserDao userDao = new UserDaoImplForOracle();

这样一来就违背了开闭原则OCP,所以提出面向接口编程,请看以下代码:

完全面向接口

这就是完全面向接口编程,才符合依赖倒置原则。那你可能会问,这样userDao是null,在执行的时候就会出现空指针异常呀。你说的有道理,确实是这样的,所以我们要解决这个问题。解决空指针异常的问题,其实就是解决两个核心的问题:

  • 第一个问题:谁来负责对象的创建。【也就是说谁来:new UserDaoImplForOracle()/new UserDaoImplForMySQL()】
  • 第二个问题:谁来负责把创建的对象赋到这个属性上。【也就是说谁来把上面创建的对象赋给userDao属性】

如果我们把以上两个核心问题解决了,就可以做到既符合OCP开闭原则,又符合依赖倒置原则。

AOP

即面向切面编程

一般一个系统当中都会有一些系统服务,例如:日志、事务管理、安全等。这些系统服务被称为:交叉业务

这些交叉业务几乎是通用的,不管你是做银行账户转账,还是删除用户数据。日志、事务管理、安全,这些都是需要做的。

如果在每一个业务处理过程当中,都掺杂这些交叉业务代码进去的话,存在两方面问题:

  • 第一:交叉业务代码在多个业务流程中反复出现,显然这个交叉业务代码没有得到复用。并且修改这些交叉业务代码的话,需要修改多处。
  • 第二:程序员无法专注核心业务代码的编写,在编写核心业务代码的同时还需要处理这些交叉业务。

使用AOP可以很轻松的解决以上问题。

3.死锁是什么?如何预防和避免死锁?

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。

如何预防?

首先看死锁是怎么产生的,产生死锁有四个必要条件:

  1. 互斥条件:该资源任意一个时刻只由一个线程占用。
  2. 请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放。
  3. 不剥夺条件:线程已获得的资源在未使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。
  4. 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。

所以只需要破坏死锁的产生的必要条件即可:

  1. 破坏请求与保持条件 :一次性申请所有的资源。

  2. 破坏不剥夺条件 :占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。

  3. 破坏循环等待条件 :靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。

如何避免?

避免死锁就是在资源分配时,借助于算法(比如银行家算法)对资源分配进行计算评估,使其进入安全状态。

安全状态 指的是系统能够按照某种线程推进顺序(P1、P2、P3…Pn)来为每个线程分配所需资源,直到满足每个线程对资源的最大需求,使每个线程都可顺利完成。称 <P1、P2、P3.....Pn> 序列为安全序列。

第六天

1.什么是反射机制?说说反射机制的优缺点、应用场景?

反射,即程序可以访问、检测和修改它本身状态或行为的一种能力。

Java反射机制主要提供了以下功能:

1.在运行时判断任意一个对象所属的类。

2.在运行时构造任意一个类的对象。

3.在运行时判断任意一个类所具有的成员变量和方法。

4.在运行时调用任意一个对象的方法。

优点:运行期类型的判断,class.forName() 动态加载类,提高代码的灵活度

缺点:性能开销、安全限制、内部暴露

应用场景:动态代理、JDBC 的数据库的连接、Spring 通过 XML 配置模式装载 Bean 的过程(以下为过程步骤)

  1. 将程序内所有 XML 或 Properties 配置文件加载入内存中
  2. Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息
  3. 使用反射机制,根据这个字符串获得某个类的Class实例
  4. 动态配置实例的属性

2.数据库索引是什么,有什么作用,什么场景适合使用索引?

官方定义:一种帮助mysql提高查询效率的数据结构。数据结构为B+树

索引就相当于一本书的目录,通过目录可以快速的找到对应的资源。

应用场景:

  • 数据量庞大。(根据客户的需求,根据线上的环境)
  • 该字段很少的DML操作。(因为字段进行修改操作,索引也需要维护)
  • 该字段经常出现在where子句中。(经常根据哪个字段查询)

3.HTTP 有哪些常见的状态码?

分类:

1xx:表示目前是协议的中间状态,还需要后续请求
2xx:表示请求成功
3xx:表示重定向状态,需要重新请求
4xx:表示请求报文错误
5xx:服务器端错误

常用:

101 切换请求协议,从 HTTP 切换到 WebSocket
200 请求成功,有响应体
301 永久重定向:会缓存
302 临时重定向:不会缓存
304 协商缓存命中
403 服务器禁止访问
404 资源未找到
400 请求错误
500 服务器端错误
503 服务器繁忙

第七天

1.访问修饰符 public、private、protected,以及无修饰符(默认)时的区别

2.线程间有哪些通信方式?

线程间通信方式有三种:共享内存、消息传递、管道流

  • 共享内存:线程之间共享程序的公共状态,线程之间通过读-写内存中的公共状态来隐式通信。

    例如:volatile共享内存,volatile关键字保证了共享变量的可见性,任何线程需要读取时都要到内存中读取(确保获得最新值)

  • 消息传递:线程之间没有公共的状态,线程之间必须通过明确的发送信息来显示的进行通信。

    例如:wait/notify等待通知方式、join方式

  • 管道流:管道输入/输出流和普通的文件输入/输出流或者网络输入/输出流不同之处在于,它主要 用于线程之间的数据传输,而传输的媒介为内存。

详解地址

3.什么是分布式?为什么需要分布式?

分布式系统是若干独立计算机(服务器)的集合,这些计算机对于用户来说就像单个相关系统,分布式系统(distributed system)是建立在网络之上的服务器端一种结构。

为了解决传统单体服务架构带来的各种问题,代码数量庞大,迭代测试维护困难,可能因为一处改动测试不到位造成整个服务瘫痪等问题,分布式系统就是将一个大的服务拆分成几十个甚至上百个微小的服务。如果把单体架构服务器比做篮子,那代码就是鸡蛋,不要让所有鸡蛋别装在一个篮子里,也方便大家分工开发。

优点:

  • 系统可用性提升
  • 系统并发能力提升
  • 容错能力提升
  • 低延迟

第八天

1.你是怎么做 MySQL 数据备份的?比如怎么恢复半个月前的数据?

针对不同的场景

  1. 如果数据量较小,可以直接cp,复制数据库文件
  2. 如果数据量还行,先使用mysqldump对数据库进行完全备份, 然后定期备份BINARY LOG达到增量备份的效果

基于时间点的恢复依赖的是 binlog 日志,需要从 binlog 中找过从备份点到恢复点的所有日志。

2.什么是消息队列?消息队列有哪些应用场景?

概述

消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即返回,由消息系统来确保消息的可靠传递。

消息发布者只管把消息发布到 MQ 中而不用管谁来取,消息使用者只管从 MQ 中取消息而不管是谁发布的。这样发布者和使用者都不用知道对方的存在

应用场景

1.流量消峰:

用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面。

秒杀业务根据消息队列中的请求信息,再做后续处理。

2.应用解耦:

订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功

库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作

假如:在下单时库存系统不能正常使用。也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。实现订单系统与库存系统的应用解耦。

3.异步处理:

按照以上约定,用户的响应时间相当于是注册信息写入数据库的时间,也就是50毫秒。注册邮件,发送短信写入消息队列后,直接返回,因此写入消息队列的速度很快,基本可以忽略,因此用户的响应时间可能是50毫秒。因此架构改变后,系统的吞吐量提高到每秒20QPS。比串行提高了3倍,比并行提高了两倍!

4.日志处理

日志采集客户端,负责日志数据采集,定时写受写入Kafka队列;Kafka消息队列,负责日志数据的接收,存储和转发;日志处理应用:订阅并消费kafka队列中的日志数据。

3.设计模式是什么?为什么要学习和使用设计模式?

设计模式(Design pattern) 是解决软件开发某些特定问题而提出的一些解决方案也可以理解成解决问题的一些思路。通过设计模式可以帮助我们增强代码的可重用性、可扩充性、 可维护性、灵活性好。我们使用设计模式最终的目的是实现代码的 高内聚低耦合

第九天

1.一条 SQL 语句在 MySQL 中的执行过程是怎样的?

流程

  1. 通过连接器连接到数据库
  2. 如果是查询语句,且命中缓存,则直接返回缓存结果
  3. 没有命中缓存的话,SQL 语句就会经过分析器,分析器说白了就是要先看你的 SQL 语句要干嘛,再检查你的 SQL 语句语法是否正确。
  4. 然后到优化器,按照 MySQL 认为最优的方案去执行。
  5. 最后到执行器,执行语句,然后从存储引擎返回数据。 执行语句之前会先判断是否有权限,如果没有权限的话,就会报错。

2.什么是 IOC,简单讲一下 Spring IOC 的实现机制?

ioc:即控制反转,将对象的创建交给容器管理。

实现机制:简单工厂 + 反射

简单工厂就是调用这个方法 BeanFactory.getBean(name);

反射就是在工厂模式getBean()方法中通过反射的方式来创建Bean。

– 反射会根据getBean(name), 传入的name来通过以下两种配置方式找到类全路径然后进行创建Bean对象。

3.并发和并行有什么区别?同步和异步有什么区别?

并发:

早期计算机的 CPU 都是单核的,一个 CPU 在同一时间只能执行一个进程/线程,当系统中有多个进程/线程等待执行时,CPU 只能执行完一个再执行下一个。

所谓并发,就是通过一种算法将 CPU 资源合理地分配给多个任务,当一个任务执行 I/O 操作时,CPU 可以转而执行其它的任务

虽然 CPU 在同一时刻只能执行一个任务,但是通过将 CPU 的使用权在恰当的时机分配给不同的任务,使得多个任务在视觉上看起来是一起执行的。

并行:

并行则是针对多核 CPU 提出的。和单核 CPU 不同,多核 CPU 真正实现了“同时执行多个任务”

多核 CPU 的每个核心都可以独立地执行一个任务,而且多个核心之间不会相互干扰。在不同核心上执行的多个任务,是真正地同时运行,这种状态就叫做并行。

并发与并行的区别

  • 并发:两个及两个以上的作业在同一 时间段 内执行。
  • 并行:两个及两个以上的作业在同一 时刻 执行。

最关键的点是:是否是 同时 执行。

同步和异步的区别

  • 同步 : 发出一个调用之后,在没有得到结果之前, 该调用就不可以返回,一直等待。
  • 异步 :调用在发出之后,不用等待返回结果,该调用直接返回

第十天

1.String 和 StringBuffer、StringBuilder 的区别是什么?

String:用于字符串操作,属于不可变类

StringBuilder:与 StringBuffer 类似,都是字符串缓冲区,但线程不安全

StringBuffer:也用于字符串操作,不同之处是 StringBuffer 属于可变类,对方法加了同步锁,线程安全

2.MySQL 中的索引是怎么实现的?B+ 树是什么,B 树和 B+ 树的区别,为什么 MySQL 要用 B+ 树?

MySQL索引的实现依赖其底层数据结构B+树。

B+树是B树的变体,有着更高的查询性能。一个m阶的B+树有以下特征:

  • 有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。

  • 所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。

  • 所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。

MySQL使用B+树的原因:

  • B+树能显著减少IO次数,提高效率

  • B+树的查询效率更加稳定,因为数据放在叶子节点

  • B+树能提高范围查询的效率,因为叶子节点指向下一个叶子节点

3.Spring 框架中都用到了哪些设计模式?

  1. 工厂设计模式

    Spring使用工厂模式可以通过BeanFactory或ApplicationContext创建bean对象。

    两者对比:

    BeanFactory :延迟注入(使用到某个 bean 的时候才会注入),相比于BeanFactory来说会占用更少的内存,程序启动速度更快。

    ApplicationContext :容器启动的时候,不管你用没用到,一次性创建所有 bean 。BeanFactory 仅提供了最基本的依赖注入支持,ApplicationContext 扩展了 BeanFactory ,除了有BeanFactory的功能还有额外更多功能,所以一般开发人员使用ApplicationContext会更多。

  2. 单例模式

    Spring中bean的默认作用域就是singleton。

    Spring实现单例的方式:

    xml格式:<bean id="userService" class="top.snailclimb.UserService" scope="singleton"/>
    注解:@Scope(value = "singleton")
    
  3. 代理模式

    AOP就是基于动态代理的

  4. 观察者模式

    观察者设计模式是一种对象行为模式。它表示的是一种对象与对象之间具有依赖关系,当一个对象发生改变时,这个对象锁依赖的对象也会做出反应。Spring事件驱动模型就是观察者模式很经典的应用。

  5. 适配器模式

    适配器设计模式将一个接口转换成客户希望的另一个接口,适配器模式使得接口不兼容的那些类可以一起工作,其别名为包装器。在Spring MVC中,DispatcherServlet根据请求信息调用HandlerMapping,解析请求对应的Handler,解析到对应的Handler(也就是我们常说的Controller控制器)后,开始由HandlerAdapter适配器处理。

第十一天

1.MySQL 事务有哪些隔离级别、分别有什么特点,以及 MySQL 的默认隔离级别是什么?

四种隔离级别:

  1. 读未提交:事务可以读取未提交的数据,可能发生脏读、幻读、不可重复读
  2. 读已提交:只能读取已经提交的数据,可以避免脏读,没有解决幻读、不可重复读
  3. 可重复度:保证同一个事务中多次读取同一数据的结果是一致的,避免了脏读和不可重复读,没有解决幻读
  4. 序列化读:最高隔离级别,避免所有的问题,但是并发性能非常低,开销大

2.讲一下 Redis 的单线程模型,IO 多路复用是什么?

Redis是一款基于内存的键值存储系统,采用单线程模型。在Redis中所有的客户端请求都是由一个单线程来处理的,这个单线程不断地从客户端套接字中读取命令请求,并将命令放到一个请求队列中。

单线程模型的优点是可以避免多线程并发访问数据时的竞争和死锁问题,简化了系统的设计和调试。由于Redis的内存访问速度非常快,因此单线程处理请求也能够保证足够的性能。

IO多路复用是指:在一个线程中同时监听多个文件描述符,一旦某个文件描述符就绪,就立即处理对应的事件。在Redis中,采用的是epoll的IO多路复用技术,可以实现高效的事件监听和响应。

3.什么是 BIO、NIO、AIO?

BIO(Blocking IO)是传统的IO模型,它在读写数据时会阻塞线程,直到数据读写完成,适用于并发量不高的场景。

NIO(Non-blocking IO)是Java的新IO模型,它在读写数据时不会阻塞线程,而是通过轮询的方式检查是否有数据可读写,适用于并发量较高的场景

AIO(Asynchronous IO)是JDK7引入的新IO模型,它的读写方式与NIO相似,但是在读写数据时,不需要自己手动轮询是否有数据可读写,而是交由系统完成,适用于高并发且处理较大数据量的场景。

第十二天

1.意向锁是什么?有什么作用?它是表级锁还是行级锁?

  1. 意向锁是什么

    意向锁是一种 MySQL 数据库中的锁,用于表级锁协调多个行级锁的使用。在表级锁定一个表之前,MySQL 需要先获得一个意向锁,以表明要获取的锁类型(读锁或写锁)

  2. 作用

    意向共享锁和意向独占锁是表级锁,不会和行级的共享锁和独占锁发生冲突,而且意向锁之间也不会发生冲突,只会和共享表锁(lock tables … read)和独占表锁(lock tables … write)发生冲突。

    表锁和行锁是满足读读共享、读写互斥、写写互斥的

    作用:为了快速判断表里是否有记录被加锁

  3. 行级锁

    表级别锁有以下几种

    • 表锁
    • 元数据锁(MDL)
    • 意向锁
    • AUTO-INC锁

    所以意向锁是表级别锁

2.Spring、SpringMVC、SpringBoot 三者之间是什么关系?

Spring、SpringMVC、SpringBoot 是三个独立的框架,它们之间的关系是:

  1. Spring 是一个 Java 的轻量级应用框架,提供了基于 IoCAOP 的支持,用于构建企业级应用。Spring 有多个模块,包括 Spring Core、Spring Context、Spring JDBC、Spring Web 等,每个模块提供了不同的功能。
  2. SpringMVC 是 Spring 框架的一部分,是基于 MVC 设计模式的 Web 框架,用于构建 Web 应用程序。它提供了控制器、视图解析器、数据绑定、异常处理等功能,使得开发 Web 应用变得更加简单。SpringMVC 还支持 RESTful 架构。
  3. SpringBoot 是基于 Spring 框架的一个开发框架,用于快速构建独立的、生产级别的 Spring 应用程序。它通过自动配置约定优于配置的方式,简化了 Spring 应用程序的配置和开发过程。SpringBoot 集成了很多常用的第三方库和工具,例如 Spring Data、Spring Security、Thymeleaf、Logback 等,可以极大地提高开发效率。

因此,SpringBoot 可以看作是在 Spring 的基础上,通过自动配置和约定优于配置的方式,提供了更加简单、快速的开发体验。而 SpringMVC 则是 Spring 框架中用于构建 Web 应用程序的模块

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

Redis 中的 String 类型底层实现是一个简单动态字符串SDS,Simple Dynamic String),也就是字符串动态增长实现的一种方式。

SDS 是 Redis 自己实现的字符串库,相对于 C 语言原生的字符串,SDS 在空间使用上更加灵活,而且支持 O(1) 复杂度的长度计算,避免了 C 语言字符串计算长度时的 O(N) 时空复杂度问题。

第十三天

1.有哪些注解可以注入 Bean?@Autowired 和 @Resource 的区别?

在 Spring 框架中,常用的注入 Bean 的注解包括:

  • @Autowired:自动注入,按照类型自动装配,如果有多个同类型的 Bean,则需要通过 @Qualifier 指定具体的 Bean。
  • @Resource:Java 自带的注入方式,按照名称自动装配,默认是按照属性名称进行匹配,如果需要按照 Bean 的名称进行匹配,可以使用 @Resource(name=“beanName”)。
  • @Inject:和 @Autowired 类似,也是按照类型进行自动装配,但是 @Inject 注解是 JSR-330 提供的,而 @Autowired 注解是 Spring 框架提供的。
  • @Value:用于注入配置文件中的属性值,可以指定默认值。
  • @Component:用于声明一个 Bean,作用类似于 XML 中的 标签。

以上注解都可以用于注入 Bean,不同的注解之间的区别主要在于注入方式和实现方式的不同。@Autowired 和 @Resource 最常用,其中 @Autowired 按照类型自动装配更为常用,而 @Resource 按照名称自动装配则比较适合需要明确指定 Bean 名称的情况。

2.请你介绍下 JVM 内存模型,分为哪些区域?各区域的作用是什么?

JVM 内存模型分为以下几个区域:

  1. 程序计数器(Program Counter Register):每个线程都有自己的程序计数器,用于指示当前线程执行的字节码指令的行号,以便线程执行时能够回到正确的位置。
  2. 虚拟机栈(JVM Stack):也称为 Java 方法栈,用于存储方法执行时的局部变量表、操作数栈、动态链接、方法出口等信息。每个线程在执行一个方法时,都会为该方法分配一个栈帧,并将该栈帧压入虚拟机栈,当方法执行完毕后,虚拟机会将其出栈。
  3. 本地方法栈(Native Method Stack):与虚拟机栈类似,用于存储本地方法的执行信息。
  4. 堆(Heap):用于存储对象实例,是 JVM 中最大的一块内存区域。堆是被所有线程共享的,当创建一个新对象时,对象实例存储在堆中,堆中存储的对象实例都有一个标记用于标记对象是否存活。垃圾回收器会周期性地回收那些没有被标记为存活的对象。
  5. 方法区(Method Area):用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区也是被所有线程共享的。

其中,程序计数器、虚拟机栈、本地方法栈是线程私有的,堆、方法区是线程共享的。

3.Linux 中的硬链接和软连接是什么,二者有什么区别?

在 Linux 文件系统中,硬链接(hard link)和软链接(symbolic link)都是一种文件链接的方式,可以用于将一个文件链接到另一个文件上。它们的主要区别在于创建方式、所占空间和使用限制等方面。

硬链接是通过在文件系统中创建一个新的目录项(directory entry)指向同一文件 inode 的位置来实现的。因为硬链接实际上是指向同一 inode,所以如果原文件被删除,硬链接依然能够访问到原文件的内容。硬链接的使用范围比较受限,因为硬链接只能指向同一个文件系统内的文件,不能跨文件系统创建。

软链接是通过在文件系统中创建一个新的文件来实现的,该文件中包含指向另一个文件的路径。软链接可以跨文件系统创建,并且可以指向任何类型的文件。但是,当原文件被删除时,软链接将会失效。

总的来说,硬链接更加高效,因为它只是添加了一个新的目录项,所以对磁盘空间的消耗比软链接要小。但是,硬链接不能跨文件系统,所以在实际应用中需要根据具体的需求来选择使用哪种链接方式。

Linux命令

Linux 系统下提供 ln 指令来进行文件链接

ln -s bar.txt foo.txt

ls 查看当前目录下的文件

➜ ll
total 1.2M
-rw-rw-r--. 1 Nova Nova    0 Aug 11 14:43  bar.txt
lrwxrwxrwx. 1 Nova Nova    7 Aug 11 14:43  foo.txt -> bar.txt

这个foo.txt,就是一个文件链接,文件链接主要分为硬链接和软链接,通过查看ln --help

➜  Desktop ln --help
Usage: ln [OPTION]... [-T] TARGET LINK_NAME
Create hard links by default, symbolic links with --symbolic.

Mandatory arguments to long options are mandatory for short options too.
  -s, --symbolic              make symbolic links instead of hard links

ln 指令默认创建的是硬链接,如果加入了-s参数,则会生成一个软链接。

第十四天

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

使用**有序集合(Sorted Set)**来存储排行榜数据,以用户得分作为分数(score),用户 ID 作为成员(member)。

当用户得分改变时,使用 Redis 的 ZADD 命令将用户的分数更新到有序集合中。

获取排行榜数据时,使用 Redis 的 ZREVRANGE 命令按分数倒序获取有序集合中的成员。

可以使用 Redis 的 ZSCORE 命令获取某个用户的分数,或使用 ZREVRANK 命令获取某个用户的排名。

2.什么是网关,网关的作用

网关(Gateway)是在计算机网络中用于连接两个独立的网络的设备,它能够在两个不同协议的网络之间传递数据。在互联网中,网关是一个可以连接不同协议的网络的设备,比如说可以连接局域网和互联网,它可以把局域网的内部网络地址转换成互联网上的合法地址,从而使得局域网内的主机可以与外界通信。

在计算机系统中,网关可以用于实现负载均衡、安全过滤、协议转换等功能。具体来说,网关可以分为以下几种:

  • 应用网关:用于应用层协议的处理,如 HTTP、SMTP 等。
  • 数据库网关:用于数据库访问的控制和管理。
  • 通信网关:用于不同通信协议之间的数据交换,如 TCP/IP、UDP/IP 等。
  • API 网关:用于管理和转发 API 请求,实现 API 的授权、限流、监控等功能。

3.线程的生命周期是什么,线程有几种状态,什么是上下文切换?

线程的生命周期通常包括五种状态:新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和终止(Terminated)。其中:

  • 新建状态是指当线程对象创建后,就进入了新建状态。此时它已经有了相应的内存空间和其他资源,但还没有开始运行。
  • 就绪状态是指当线程对象调用 start() 方法后,线程进入了就绪状态。此时它已经具备了运行的条件,只等 CPU 分配资源,让其开始执行。
  • 运行状态是指当线程对象获得 CPU 资源后,就开始执行 run() 方法中的代码,线程处于运行状态。
  • 阻塞状态是指线程在某些特定情况下会被挂起,暂时停止执行。当线程处于阻塞状态时,它并不会占用 CPU 资源。
  • 终止状态是指当线程的 run() 方法执行完毕或者因异常退出时,线程进入了终止状态。此时,该线程不再占用 CPU 资源,也不再执行任何代码。

在线程的生命周期中,线程状态的转换通常是由操作系统调度和控制的。当线程的状态发生变化时,需要进行上下文切换,即保存当前线程的状态和上下文信息,并恢复另一个线程的状态和上下文信息,使其能够继续执行。上下文切换会带来一定的开销,因此需要尽可能减少线程之间的切换次数

第十五天

1.MVCC 是什么?InnoDB 是如何实现 MVCC 机制的?

MVCC 是指多版本并发控制(Multiversion Concurrency Control),是一种并发控制机制,常用于数据库系统中,用于实现事务的并发控制。它允许在同一时间多个事务对同一个数据集合进行读取操作,同时防止数据不一致和其他并发问题。

InnoDB 是 MySQL 中最常用的存储引擎之一,它的 MVCC 实现是通过在每行记录中添加两个隐藏的列,分别记录行的创建时间和过期时间,以此来判断事务对该行记录的可见性

2.Redis 的持久化机制有哪些?说说各自的优缺点和应用场景?

  1. RDB持久化机制

    RDB 持久化机制是指将 Redis 在内存中的数据以快照的形式写入磁盘中,可以手动或自动执行快照操作,将数据集的状态保存到一个 RDB 文件中

    优点:

    • RDB 机制适合在数据集比较大时进行备份操作,因为它可以生成一个非常紧凑、经过压缩的数据文件,对于备份、恢复、迁移数据都很方便。
    • RDB 机制在 Redis 重启时比 AOF 机制更快地将 Redis 恢复到内存中。

    缺点:

    • RDB 机制可能会出现数据丢失,因为数据是周期性地进行备份,一旦 Redis 出现问题并且上一次备份之后还没有进行过数据变更,那么这部分数据将会丢失。
    • RDB 机制会造成一定的 IO 压力,当数据集比较大时,进行备份操作可能会阻塞 Redis 服务器进程。
  2. AOF持久化机制

    AOF 持久化机制是指将 Redis 在内存中的操作命令以追加的形式写入到磁盘中的 AOF 文件,AOF 文件记录了 Redis 在内存中的操作过程,只要在 Redis 重启后重新执行 AOF 文件中的操作命令即可将数据恢复到内存中。

    优点:

    • AOF 机制比 RDB 机制更加可靠,因为 AOF 文件记录了 Redis 执行的所有操作命令,可以确保数据不丢失。
    • AOF 机制在恢复大数据集时更加稳健,因为 AOF 文件记录了数据的操作过程,可以确保每一次操作都被正确地执行。

    缺点:

    • AOF 机制生成的 AOF 文件比 RDB 文件更大,当数据集比较大时,AOF 文件会比 RDB 文件占用更多的磁盘空间。
    • AOF 机制对于数据恢复的时间比 RDB 机制更加耗时,因为要重新执行 AOF 文件中的所有操作命令。

综上所述,RDB 适合用于数据集较大、备份、恢复数据和迁移数据等场景,AOF 适合用于数据可靠性要求高、数据恢复稳健等场景。

第十六天

1.Dubbo 是什么?是否了解过它的架构设计?

  1. Dubbo 是一个高性能、轻量级的开源 Java RPC 框架,它提供了完整的 RPC 协议栈,包括服务发布、服务引用、负载均衡、容错、服务治理和服务监控等功能
  2. RPC 全称为 remote procedure call,即远程过程调用
  3. Dubbo 的架构设计主要包括服务提供者、服务消费者、注册中心和监控中心四个角色
    • 服务提供者:提供服务的实现,并通过注册中心将自己注册到服务中心
    • 服务消费者:通过注册中心发现可调用服务,并根据附在均衡策略选择一个服务调用
    • 注册中心:负责服务的注册,发现和路由
    • 监控中心:服务的统计和监控

2.synchronized 关键字是什么,有什么作用?

synchronized 是 Java 中的一个关键字,用于实现线程同步。具体来说,synchronized 用于修饰方法或代码块,使得同一时刻只能有一个线程访问被修饰的代码,其他线程需要等待当前线程执行完毕后才能访问。

synchronized 主要用于解决多线程并发访问共享资源时出现的线程安全问题

3.如何设计一个点赞系统?

设计一个点赞系统可以分为以下几个步骤:

  • 确定需求:需要明确点赞的对象是什么,是否需要计数等信息,同时需要考虑点赞的业务场景,如用户点赞、文章点赞等。
  • 数据库设计:需要设计点赞相关的数据表,可以包含点赞者 ID、被点赞对象 ID、点赞时间等字段。
  • 接口设计:需要设计点赞相关的接口,包括点赞、取消点赞、查询点赞数等操作。
  • 业务逻辑实现:在接口中实现点赞相关的业务逻辑,包括判断点赞状态、更新点赞数、更新点赞状态等操作。
  • 安全性考虑:需要考虑并发访问的情况,可以使用分布式锁来保证数据一致性安全性
  • 性能优化:如果点赞系统的访问量很高,可以使用缓存来提高性能,比如使用 Redis 来缓存点赞数等信息。
  • 监控和日志:需要对点赞系统进行监控和日志记录,以便及时发现和排查问题。

总之,设计一个点赞系统需要综合考虑需求、数据库设计、接口设计、业务逻辑实现、安全性、性能优化等方面,同时需要不断优化和完善。

第十七天

1.什么是内部类? 内部类的分类有哪些 ?内部类的优点 ,内部类有哪些应用场景?

内部类是定义在另一个类中的类。Java 中内部类主要分为成员内部类、静态内部类、局部内部类和匿名内部类四种。

  1. 成员内部类:定义在另一个类的内部,并且与其它成员变量和方法平级,可以访问外部类的所有成员变量和方法。使用方式:
Outer.Inner inner = new Outer().new Inner()。
  1. 静态内部类:定义在另一个类的内部,但是要用 static 修饰。只能访问外部类的静态成员变量和方法。使用方式:
Outer.Inner inner = new Outer.Inner()。
  1. 局部内部类:定义在方法中,作用域仅限于方法内部。与局部变量类似,不能使用访问控制符修饰。使用方式:在方法中直接实例化。
  2. 匿名内部类:没有名字的内部类。使用方式:new 接口或者抽象类() { } 或 new 父类() { }。

内部类的优点:

  • 可以访问外部类的私有成员变量和方法。
  • 可以隐藏实现细节。
  • 便于编写和维护,提高代码的可读性和可维护性。
  • 内部类可以很好地解决Java中单继承的问题。

2.覆盖索引和联合索引是什么?讲一下索引的最左前缀匹配原则。

覆盖索引是指一个包含了所有查询需要的列的索引,查询时可以直接从索引中取到需要的数据,而不需要再回到表中查找,从而可以提高查询效率。

联合索引是指使用多个列组合起来作为一个索引,可以同时查询多个列,以提高查询效率。联合索引可以包含多个列,但是查询时只能使用前缀列进行查询

最左前缀匹配原则:

如果一个联合索引包含了多个列,那么在查询时只能使用前面的列进行匹配

例如,一个联合索引包含了 A、B、C 三列,那么查询时只能使用 A、AB 或 ABC 进行匹配,而不能只使用 B 或 C 进行匹配。这是因为如果查询时使用的列不是最左前缀列,那么 MySQL 就无法使用索引进行查询,会导致全表扫描,从而降低查询效率。

3.Spring 如何处理线程并发问题,ThreadLocal 你了解过吗?

Spring 框架中处理线程并发问题的方式包括以下几种:

  • 同步关键字 synchronized:使用 synchronized 关键字可以对共享资源进行加锁,从而保证多线程访问时的同步性。但是,synchronized 对性能会产生一定的影响,并且容易导致死锁等问题。
  • Lock 接口:Lock 接口提供了比 synchronized 更加灵活的加锁方式,并且可以防止死锁问题的发生。但是,Lock 接口的使用相对较复杂,需要手动进行加锁和解锁操作。
  • ThreadLocal 类:ThreadLocal 类提供了线程本地变量的功能,可以让每个线程拥有自己的变量副本,从而避免了多个线程之间的共享问题。但是,ThreadLocal 类的使用需要注意内存泄漏问题。