暑期实习面试常问的八股50题(上)

https://www.yuque.com/njitzhouxin/fmqwg4/pm875xva0ggv9qqg?singleDoc# 《面试常问的一些八股整理》

详细的内容可以查看我整理的语雀笔记,题目会一直更新。

都是我在找暑期实习遇到的一些八股

1.Java 反射的理解

1. 反射是程序在运行的动态获取类的信息、操作类的属性和方法。
动态加载类和创建实列,访问类的属性和调用类的方法,提高了程序的灵活性。

反射有四种获取类对象的方法,class.forName()加载、类的名称.class

()、对象名称.getclass()、类加载器 ClassLoader 来加载类。

反射主要的内容:

Class 类 、Filed 类的属性字段、 Method 类的方法、Constructor 类的构造方法创建对象。

  public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, NoSuchFieldException, InvocationTargetException {
        // 通过类名称.class
           Class<Person> personClass = Person.class;    
      //class.forName()加载
        Class<?> aClass = Class.forName("design_patterns.tx.Person");
      //创建一个类加载器
        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        Class<Person> personClass = (Class<Person>) classLoader.loadClass("design_patterns.tx.Person");
      
        Person person = personClass.newInstance();
        
        Field name = personClass.getDeclaredField("name");
        name.setAccessible(true);
        Object o = name.get(person);
        name.set(person,"lisi");
        //获得方法
        Method dance = personClass.getMethod("dance", String.class);
        //通过invoke来激活方法
        dance.invoke(person,name.get(person));
         //获取所有的注解方法
        Annotation[] annotation = personClass.getAnnotations();
    }

2. 代理模式 动态和静态、JDK 和 CGlib

代理模式对原来的对象进行增强,生成代理对象。加强原来对象的操作。

静态代理,为每一个代理类创建接口和代理类,较为复杂。

动态代理分为 jdk 动态代理,主要是 java.lang.reflect.Proxy 类的 newinstance 方法,传入三个参数 类加载器、类实现的接口、InvocationHandler 接口.实现对象的创建

还有一种 CGlib 动态代理,基于字节码文件生成一个子类继承当前的类来实现加强,实现起来性能消耗更大。

JDK 动态代理

基于字节码技术,在运行时动态生成目标类的子类,通过继承目标类实现代理,适用于没有接口的类。可以对普通类进行代理,如果方法被 final 修饰那么就不能被代理了。SpringAOP 默认使用的就是 CGLIB。

SpringAop 底层默认使用的就是 CGLIB,通过加载字节码文件生成动态

JDK 动态代理实现

public class CarFactory {
    public static Object  getProxy(Object obj){
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),new Handler());

    }

    static class  Handler implements InvocationHandler{

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //proxy 是代理对象
            //method 是对象的方法
            // args 是参数信息
            return  null;
        }
    }
}

3. 线程池的参数、原理、拒绝策略。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
ExecutorService executorService = Executors.newFixedThreadPool(10);

execute()没有返回值,submit 返回 future 对象,用来检查任务是否完成,获取任务结果或者取消等。

通过 sumbit 拿到的是一个 Future 对象,可以拿到对应的异常信息的。

  System.out.println(future.get());

面试会问线程的拒绝策略有哪些:

复用线程,减少线程的创建,提高系统的资源效率。

画板

4.AOP 的原理、应用场景、切面有什么注意地方

AOP 底层是动态代理,SpringAOP 默认是用的 CGLIB 来实现的..

AOP 应用场景: 事务管理,日志,权限控制,等都使用了 AOP.

编写 AOP 时候的注意点:

  1. 比如切点表达式,有两种实现方式
@Pointcut("execution(public * com.example.service.*.*(..))")
public void serviceLayer() {}

通过 execution 定义切点

@Pointcut("@annotation(com.example.Loggable)")
public void loggableMethod() {}

还有通过加注解来实现切点.

多个切面作用同一个方法的时候,需要控制顺序.

@AfterThrowing(pointcut = "serviceLayer()", throwing = "ex")
public void handleException(JoinPoint jp, Exception ex) {
    // 记录异常上下文信息
    log.error("方法 {} 抛出异常: {}", jp.getSignature(), ex.getMessage());
}

5. 死锁的条件、如何优化和防止死锁

操作系统的死锁概念

死锁是多线程在执行过程中,因为争夺资源而造成的一种相互等待额现象,导致这些线程都无法继续执行下去。

写一个死锁的代码:

package design_patterns.tx;
public class SXA implements  Runnable{
    @Override
    public void run() {
         synchronized (SXA.class){
             System.out.println("A在获取锁");
             synchronized (SXB.class){
                 System.out.println("B在获取锁");
             }
         }
    }
}
package design_patterns.tx;

public class SXB implements Runnable
{
    @Override
    public void run() {
        synchronized (SXB.class){
            System.out.println("B在获取锁");
            synchronized (SXA.class){
                System.out.println("A在获取锁");
            }
        }
    }
    //同时启动 都在等待对方去释放锁
    public static void main(String[] args) {
        new Thread(new SXA()).start();
        new Thread(new SXB()).start();
    }
}
同时启动 A需要等待B释放锁,B需要等待A释放锁,相互等待就进入了死锁的状态

画板

6.HTTP 状态码

画板

502、504 的区别

502 bad gateway 从上游接收到的内容错误或者收到无效响应

504 gateway timeout 网关或者代理服务器等待上游服务器响应超时,返回 504 报错。

7 讲一讲异常体系、项目中的异常如何处理

画板

在 Java 中的异常体系分为 Exception 和 Error,根类是 throwable

Exception 是可以自己来处理的,包括受检异和非受检,受检异常 IOException 是写代码的时候就是要处理的,数组越界、空指针是程序运行的时候才会出现,这是是非受检异常通常是 RuntimeException。

Error 是 JVM 级别的问题,通过是会让程序停止比如 OOM 内存溢出或者栈溢出等。

两个都是继承 Throwable 的

异常可以直接抛出、也可以进行手动捕获 通过 try catch finally,手动捕获异常信息。

在 spring 中提供了全局异常处理器来处理异常。

通过RestControllerAdivce实现全局异常处理

@RestControllerAdvice:用于定义全局异常处理器,作用范围覆盖所有带有 @RequestMapping 的控制器,并且返回的是 JSON 格式数据(与 @ControllerAdvice 类似,只不过前者默认使用 @ResponseBody)。

@ExceptionHandler:用来指定捕获的异常类型,可以根据不同异常类型写多个方法,实现更加细粒度的异常处理。

还可以自己定义异常处理类,继承RuntimeException

底层是由SpringMVC去控制实现的
异常捕获:DispatcherServlet 捕获异常,并依次交由已注册的 HandlerExceptionResolver 处理。

异常解析:ExceptionHandlerExceptionResolver 扫描所有 @ControllerAdvice / @RestControllerAdvice 中的 @ExceptionHandler 方法,查找匹配异常类型的方法。

8 依赖注入有哪些方式,Spring 的循环依赖

字段注入:通过 Autowired 或者 Resource 注解直接注入依赖。

Setter 注入:提供 Setter 方法来实现依赖注入。

构造函数注入:通过构造函数传递依赖保证对象创建的时候全部就绪。同时通过 final +lombok 的 RequiredArgsConstuctor 结合。

循环依赖:在 Spring 中,默认的 Bean 都是单例。当两个单例 Bean 互相引用时(例如通过 setter 注入或字段注入),就会形成循环依赖。Spring 通过三级缓存来解决这种情况。

三级缓存的作用就是 Bean 初始化的过程中提交暴露 Bean 的实列来解决循环依赖的.

9.mp 实体类和表中的字段不匹配、mp 分页查询如何实现

使用 ResultMap 标签实现表字段和 Java 字段的映射。

PageHelper 分页插件来实现分页查询的。

在 MyBatis 中,分页插件 PageHelper通常利用 MyBatis 提供的插件机制,在拦截器层面对 Executor 的方法进行拦截和修改,从而在 SQL 执行前修改 SQL 语句(例如添加 LIMIT/OFFSET 子句)或在执行后对结果进行包装。 核心是拦截了 sql 语句,添加了 limit 限制.

10.Redis 三剑客

缓存击穿、穿透、雪崩

11 消息队列对比、如何保证消息不被重复消费

常见的消息队列 rocketmq,activemq,kafka 等.

12 创建线程方式、sleep 和 wait 的区别

1.继承 Thread 类,重写 run 方法,创建线程,调用 start 方法启动线程。

2.实现 Runnable 接口。将 Runnable 接口传入到 Thread 对象中,然后再调用 start()方法。

3.线程池 通过Java 并发包下面的concurrent 创建线程池。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

sleep 是 Thread 中的方法,是一个静态方法,而 wait 是 object 类下面的方法的,需要在同步代码块中调用,并且调用该对象的锁。

sleep 线程进入休眠状态,不会释放持有的对象锁

wait 调用 wait 之后,会释放当前持有的对象锁,运行其他线程进入该同步代码块,其他线程调用 notify 的时候才会被唤醒。

wait 方法还可以作为线程之间的通信。

13.Cookie和Session的区别,JWT 是啥,Session 的缺点?

画板

因为 HTTP 是无状态的,不能保持上下文的会话,实际业务中需要保持上下文会话的,所以出现了 cookie 和 session。

cookie 是保存在客户端的,session 维持会话是保存在服务端的,为会话生成一个 session Id,然后 http 请求每次都携带这个 sessionId,服务器通过 Session Id 来获取会话数据。

优缺点:

1.cookie 存储是大小限制的,一般是 4kb 左右,Session 存储在服务器能够存储较多的信息。

2.cookie 保存在客户端存在不安全的问题,适合存储一些非铭感的数据。

3.session 保存在服务器端在集群下面会出现问题,跨不同的服务 session Id 会失效,可以通过 Redis 来存储 Session

14 事务的隔离级别

读未提交、读已提交、可重复读、串行化。

读未提交:读取到了别人没有提交的数据,比如 a 修改了数据,事务还没有提交,这个时候 b 读到了,但是这个时候 a 回滚了,就会发生脏读。

读已提交:读取的数据都是已经提交的

可重复的:前后两次数据是一样的。

读已提交、可重复读都是通过 MVCC 多版本并发控制来实现的。

15MVCC 多版本控制

通过 readView,undolog,隐藏字段来实现.

mysql8.0 和 5.7 的区别?

mysql8.0 删除了缓存、引入了索引下推等概念、包括支持更多的字符集编码

索引下推是联合索引查询的时候用来减少回表操作的.

16JVM 内存划分、GC 机制是如何运行的

堆、方法区、本地方法栈 native、虚拟机栈、程序计数器 PC

圾回收机制是自动识别和释放程序中不再被引用的内存,避免内存泄漏,减轻开发者手动管理内存的负担。

17 进程和线程的区别、协程是啥?线程安全、进程通信

进程是系统分配资源的最小单位,线程是 CPU 执行的基本单位,一个进程包含了多个线程,线程不拥有自己的资源,切换起来比较快。进程上下文切换需要保存 PCB,需要保存的信息比较多。

保证线程执行的安全可以给线程加锁。保证多个线程执行的顺序

18MySQL 锁的分类

行级锁 ,表级锁. 乐观锁 ,悲观锁等.

19acid 如何实现的, mysql 三种日志文件

三种日志文件类型 redolog 、undolog、binlog

redolog 存储的是事务日志、undo log 存储的是修改的数据用来实现 MVCC 的,binlog 存储的是二进制文件。

用来实现事务的四大特性的.

原子性 是 redolog. 隔离性 undolog 持久性 binlog.

20 一条 sql 执行的流程

Mysql 数据库分层,分为了 server 层和存储引擎层。

server 首先先建立 TCP 三次握手连接,1433 端口。

一条 sql 语句进来先进行语法和词法的分析,构建语法树。

然后经过

预处理、

优化器 :判断是否走索引等,如何查询效率更高。

执行器,最后到存储引擎层。

21sql 注入是啥,如何解决的

编写一个 sql 语句查询用户名称和密码。在输入密码的是用到了 or 1=1,or 后面是永远都为真的,直接拼接 sql 那么就会出现不安全,只需要用户名就能登录成功。

先进行预编译,然后将 sql 内容插入进来即可。不直接拼接 sql。

22http 和 https 区别,https 连接过程。

http 和 https

端口、安全、证书、建立连接方式。

端口:http 是 80 端口,https 是 443 端口

安全:http 是明文传输不安全,https 是加密传输较为安全。

23.Redis 常用的数据结构

string 用来存储验证码、 hash 结构用来存储对象、

zset 实现排行榜的存储、bitmap 实现签到等。

string set key value 实现分布式锁.

24TCP,UDP 区别、TCP 如何保证自己的可靠传输

速度、场景、安全、可靠性等考虑。

通过序号和确认号保证了接受的顺序一致性

滑动窗户实现提高发送速度、流量控制来匹配发送方和接收方的速度差异、拥塞控制实现网络中的流量控制、还包括了三次握手和四次挥手的过程。

25 前端 xss 攻击

前端 XSS(跨站脚本攻击)是一种常见的 Web 安全漏洞,攻击者通过向网页中注入恶意脚本代码,从而在其他用户浏览页面时执行这些代码,进而窃取敏感信息或篡改网页内容。

  • 反射型 XSS(Reflected XSS)
    恶意脚本作为 HTTP 请求的一部分提交,服务器将其原样返回给用户浏览器,并在浏览器中执行。这种攻击通常通过 URL 参数、表单提交等实现。

  • 存储型 XSS(Stored XSS)
    恶意脚本被存储在服务器端(例如数据库、日志文件或留言板中),在其他用户访问包含恶意脚本的页面时直接执行。存储型 XSS 危害较大,因为其影响面广且持续性较强。

  • DOM 型 XSS(DOM-based XSS)
    恶意脚本在客户端侧(浏览器中)直接利用 DOM 操作执行,而非依赖服务器响应。它通常发生在客户端脚本不安全地处理用户输入或 URL 参数时。

  • 输入验证
    对所有用户输入进行严格验证和过滤,拒绝或转义潜在的恶意代码,确保输入数据符合预期格式。

  • 输出编码
    在输出到页面前,对用户输入进行 HTML、JavaScript、URL 等多种形式的转义编码,避免浏览器将用户输入当作代码执行。

  • 使用安全的库或框架
    采用能够自动处理输入输出编码的安全框架(例如 React、Angular、Vue 等),以降低手动编码错误的风险。

  • 内容安全策略(CSP)
    配置 CSP 响应头,限制网页可以加载的资源和执行的脚本,从而降低 XSS 攻击成功的风险。

26 bitmap 位图是啥,布隆过滤器的优点和缺点

一个二进制的向量和几个 hash 函数,用来解决缓存缓存穿透问题的.

27 分布式锁如何实现的?

最基础的分布式锁 使用 set key value . key 是业务的名称 value 是线程 ID+UUID.

注意点: 1.锁要设置过期时间,不能一直锁着.

2.自己上的锁只能自己释放,别人不能释放.

28 浏览器输入网址执行的全部过程

从 TCP/IP 的四层结构去讲。 输入的是 URL,报文是通过路由器进行转发的,路由器是根据 IP 地址进行转发的,想讲 URL 转为 IP 地址,进行 DNS 解析。

解析完成之后封装 HTTP 请求报文,包含了请求行、请求头和请求体。

然后 在 传输层的时候 TCP 三次握手建立连接,确保双方都有接收和发送数据包的能力,TCP 实现的是端到端的通信。

然后到网络层,这一层封装的是 Ip 数据包。

IP 只是可以定位到小区一样的,真正识别你的是 MAC 地址,类似于有身份证,每个人都是唯一且不一样的。需要用到 ARP 协议,进行 MAC 地址查询。

然后到最下面的网络连接层,将数据包封装层比特流。一串串二进制的。

经过电脑的网卡,将数字信息转为电型号,通过集线器发送出去,经过路由器和交换机到达目的主机。

到达目的主机之后,从最下层网上,数据包不断拆开,拿到 http 请求报文,进行解析,解析完成之后 封装 http 响应报文。

响应报文到达发送端之后,浏览器需要渲染 html 包括 dom 元素等。

从上往下,然后再从下网上讲解

29HashMap 原理、扩容机制、容量 2 次幂、put 过程、自定义 key、安全的 hash

在 1.8 之前,hashmap 底层是数组+链表

1.8 之后 hashmap 底层是数组+链表/红黑树。

扩容机制当 数量达到了 容量*负载因子的时候就需要进行扩容。

自定义 key 可以添加进来,比如 Person 对象把,但是需要重写 equals 方法。

hashcode 是高位和低位进行或运算,这样是 hash 值分布的更加均匀。

hashmap 运行一个 key 为 null,运行多个 value 为 null,在并发的清空下面 hashmap 是线程不安全的。

30concurrenthashmap 底层、CAS 自旋操作、ABA 问题

1.8 之前是分段锁和链表实现的

18 之后基于 synchronized 和 CAS 自旋实现的

CAS 是用于比较内存中的值和预期的值是否相同的操作。

31 Linux 的常用命令、线上排查。

常用的命令就是 top 命令查看进程的内存和 CPU 占用情况。

jstack 也可以查看

32 ThreadLocal、内存泄露、四种引用关系

为什么会内存泄露,key 是弱引用,被 GC 回收了,但是 value 是强应用,没有被回收掉.

33String、Sbuilder、Sbuffer,字符串为什么设计 final、常量池。

String 是 final 修饰的,不能被改变。保证了并发场景下的安全性,final 修饰不能概念可以缓存 hashcode 值,同时也引出了字符串常量池的概念。

Sb 是线程不安全的,sbuffer 是线程安全的,区别就是两个类在方法上面一个加了 synchronized,另一个没有加。

34Arraylist 和 LinkedList

这边基本的特性说一说.

深入可以聊的就是 arraylist 的扩容机制和如何来优化.

copyonwriteList

35 栈内存和堆内存区别?

程序运行的时候内存被分为了栈内存和堆内存。

栈内存分配由编辑器自动分配的包括了,局部变量、方法执行、基本数据类型、对象引用等。

堆内存 主要存储的是对象,手动 new 出来的,或者 GC 自动回收。

36equals 和 hashcode 重写

基本数据类型使用==来比较,对用引用数据类型==比较的是地址值,不是比较内容是否相等。需要使用 equals 方法,默认使用的是 object 类下面的 equals 方法,本质还是==。所以需要重写 equals 方法。

hashCode 方法:在 Set 集合那边,对象 hashcode 如果不同,那么相同的对象就可能被添加到 set 集合中去了。

37 慢 sql 、sql 优化、索引失效、explain

https://www.nowcoder.com/issue/tutorial?zhuanlanId=Mz9XzX&uuid=d416b8fcaefb4fd2b4c570cf87890807

38 最左匹配原则、索引下推

39Redis 持久化机制

基于 aof 和 Rdb 来实现的持久化机制

https://www.nowcoder.com/issue/tutorial?zhuanlanId=Mz9XzX&uuid=1c74c8b21a6246018058e41b1ccde704

40Redis 哨兵机制

主从节点、哨兵、集群化。

41 快排、堆排序、归并排序

快排和归并排序都是基于递归实现的, 堆排序是基于二叉树来实现的。

42 TCP 粘包和拆包

TCP 粘包和拆包问题根本在于 TCP 协议本身的特点引起的,这是基于字节流传输的,没有明显的边界。并且发送方和接收方都通过滑动窗口来接收和发送存在缓冲区,还有最大传输单元,发送端可能会将数据包拆分,接收方可能将数据包合并。

固定首部长度,缺点是浪费空间,需要填充全部的长度。

使用分隔符类似于 http 协议的分隔符、或者在头部字段标准 tcp 报文的长度。

43.TCP 三次握手和四次挥手过程

三次握手 SYN=1,seq=x;SYN=1,ACK=1,seq=y,ack=x+1.

第三次握手 ACK=1,seq=x+1,ack=y+1。

44synchronized 和 reentrantlock

画板

创建的 lock 手动的加锁

public class Main implements Runnable {
    public  static ReentrantLock lock = new ReentrantLock();
    
    private static int i=0;

    @Override
    public void run() {
        lock.lock();
        try {
            Thread.sleep((long) Math.random());
        } catch (InterruptedException e) {
            //等待都是中断的异常
            throw new RuntimeException(e);
        }
        i++;
        lock.unlock();
    }

    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[1000];
        for (int i = 0; i < 1000; i++) {
            threads[i] = new Thread(new Main());
            threads[i].start();
        }
        // 等待所有线程完成
        for (Thread t : threads) {
            t.join();
        }
        System.out.println(i); // 现在会正确输出1000
    }
}

45 微服务:gateway、fegin、nacos

gateway 是网关支持路由和转发

fegin:是服务之间的调用

nacos 用于服务的注册和发现

46 IO 多路复用

IO 多路复用是一种能够让单个线程或进程同时监控多个 I/O 事件(如网络连接、文件读写等)的技术。其主要作用和优势包括:

这个就会聊到五种 IO 模型.阻塞 IO,非阻塞 IO,IO 多路复用. 信号 IO,异步 IO 模型.

I/O 多路复用(I/O Multiplexing) 允许一个线程同时监听多个文件描述符(Fd),并在其中任意一个 Fd 就绪时进行读写操作,从而提高 I/O 效率。常见的实现方式有 <font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">select</font><font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">poll</font><font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">epoll</font>,它们在实现机制和性能上有显著差异。

47SpringBoot 的启动过程

1.从启动类开始 SpringBootApplication 注解开始

@SpringBootApplication
public class MyApp {
    public static void main(String[] args) {
        SpringApplication.run(MyApp.class, args); // 启动入口
    }
}

2.加载 spring.factoies 实现自动装配.

  1. 启动内嵌的 tomcat 服务器

48SpringMVC 的执行过程

核心是 dispatchServlet 前端控制器。

49 讲一讲类加载机制,双亲委派机制

Java 的类加载机制是 JVM 将.class 文件加载到内存中,并转换成 Class 对象的过程。

加载->验证->准备->解析->初始化。

通过类的全限定名获取二进制字节流文件.class 文件。

双亲委派机制

当一个类加载器收到类加载请求时:

先委托给父加载器,而不是自己加载。

如果父加载器无法加载(在自己的搜索范围内找不到),才由子加载器尝试加载。

public class People {
    static {
        System.out.println("People 类初始化(静态代码块)");
    }
}
public class Student extends People{
    static {
        System.out.println("Student 类初始化(静态代码块)");
    }

    public static void main(String[] args) {
        System.out.println("----- 第一次访问 Student -----");
        new Student();

        System.out.println("\n----- 第二次访问 Student -----");
        new Student(); // 类已加载,不会再次初始化
    }
}

先加载父类,然后再加载子类的。

50 集合框架讲一讲

51 常用的设计模式(单列、策略、工厂模式、建造者模式)

52 手写单列设计模式(懒汉、饿汉、双重校验所)

53 b+的的优点,和 b+、红黑树进行比较

b+树叶子节点存储数据,非叶子节点存储索引值和节点之间的关系。叶子节点通过双向链表连接起来,可以支持范围查找。

54Redis Zset 底层结构是啥?

哈希表和跳表实现,数据量比较小的时候是压缩表 ziplist。跳表是多层的有序单链表,最底层网上数量不断变少,可以实现 logn 的时间复杂度查找。

55 JMM 内存模型

JMM 的主要目标是解决多线程环境下共享变量的可见性、原子性和有序性问题。它为开发者提供了一套规则,使得不同平台上的 Java 程序在多线程环境下的行为保持一致。

多线程下面,一个线程修改了数据另一个线程不能立刻感知到,为什么?

内存是分为主内存和工作内存的,主内存存放共享变量的内存区域,所有线程都可以访问。线程有自己的工作内存,用来存储线程使用到的变量副本。线程对变量的操作都是在工作内存中进行的,最后在同步到主内存中,使用 violate 直接操作主内存,这样可以让其他线程立即感知到。

原子性和可见、有序性:

内存屏障:编辑器和处理可能会进行指令重排序,指令排序在单线程的情况下面是可以的,通过 happens-before 规则定义了操作之间的顺序,在必要的时候进制重排序。

同步代码块: 保证同一时刻只有一个线程可以进入代码块操作,保证了原子性。

56 RBAC 权限模型

RBAC 权限模型,基于角色访问的权限模型,需要三张表才能实现。

给用户分配角色,不同的角色分配不同的权限。

用户:User : 张三,李四

角色:Role:管理员、普通用户

权限:对资源的操作 add_user、delete_user.

57 缓存一致性如何解决的?

58 Spring 事务失效场景,事务的传播行为

Spring 事务失效底层是基于 AOP 实现的,AOP 底层是基于动态代理的,所以事务失效,很多是动态代理失效。

1.方法使用非 public 来修饰,动态代理不能代理非 public 方法

2.在同一个类中调用,会绕过代理对象

3.手动捕获了异常,没有向上抛出异常

4.使用了特定的事务机制,事务没有生效

59 大文件上传的思路?

md5hash 校验、分片上传类似于 IP 数据包那种分片。

60mysql 有哪些索引?

61SpringBean 的声明周期 和作用域

62CAS是什么?是怎么工作的?常见的ABA问题怎么解决?

CAS 比较并交换 是乐观锁的一种,CAS 工作中有三个核心参数,一个是当前变量内存地址值,预期原值 A 是认为当前内存中的值,B 是希望更新的值

读取内存地址 v 的当前值标记为 current,如果等于预期值,那么就改为 B,否则不更新进行自旋的操作。

V 是内存地址,V.value 拿到值和 A 进行比较,如果相等就更新为 B。

线程 1 读取内存值为 A,线程二将值改为 B 后又改为了 A,此时线程 1 操作任然成功,但是实际共享数据已经发生了中间变化,这个就是存在的 ABA 问题。


修改共享变量的时候递增版本号,CAS 需要同时检查值和版本号。

CAS 是无锁的,减少了线程的上下文切换,但是自旋操作导致 CPU 空转。

public static void main(String[] args) {
        //定义了源自类
        AtomicInteger  i=new AtomicInteger();
        System.out.println(i.get());
        System.out.println(i.incrementAndGet());
        //对比操作
        i.compareAndExchange(2,2);
        System.out.println(i.get());
        i.set(50);
        System.out.println(i.get());
    }
#八股##暑期##后端开发#
牛牛的面试专栏 文章被收录于专栏

牛牛的面试专栏,希望自己在25年可以拿到一份大厂的SP Offer 你的点赞和收藏都是我持续更新的动力

全部评论
19事务实现错了吧
点赞 回复 分享
发布于 昨天 10:22 福建
mark一下
点赞 回复 分享
发布于 04-18 10:03 湖北

相关推荐

核心本地商业-业务研发平台4月9日1:面试官自我介绍+自我介绍2:Spring源码讲一下3:Spring源码学完什么收获4:spring的事务了解吗?,mysql的事务呢?5:spring的事务和mysql的事务有什么联系?6:项目jdk什么版本?7:默认垃圾回收器是什么?8:介绍一下ZGC和G1?9:项目性能调优怎么做的?垃圾回收器参数,jvm参数,10:Seata分布式事务?11:其他分布式事务了解吗?(模模糊糊说了MQ)12:AT和TCC说一下?13:看过12306官方的实现吗?14:既然你看过一些实现,那么你想怎么优化呢?(答了锁粒度方案,和redis方案)15:redis方案的一致性怎么解决?(答了cannal,MQ)16:redis网络波动,用于以为下单失败,但是其实redis收到消息怎么办?(当时说的MQ,但是面试官想说的不是这个,后面复盘应该是本地消息表+定时任务)17:&nbsp;项目数据库方面有什么优化?(联合索引,explan,慢查询日志,skywalking)18:加完索引,前端需要注意什么?19:数据库的什么字段适合加索引&nbsp;,什么字段不适合?&nbsp;20:Hashmap源码看过吗21:Hashmap多个线程put有什么问题?(值覆盖,极端情况下数组越界)22:值覆盖举个例子?23:极端情况下数组越界什么意思?24:还有其他的情况吗?(最后答了链表和红黑树可能会空指针异常)25:多线程用什么替代?(concurentHashmap)26:concurentHashmap1.7和1.8区别?27:concurentHashmap1.7为什么用了CAS?28:concurentHashmap1.8怎么实现?(乐观和悲观两种情况)29:1.8里的volatile是什么?30:volatile能解决线程安全问题吗?(不能)31:那能解决什么问题?32:SQL题,单表topk,审错题意了,写了快20分钟用子查询才写出来,然后面试官说有没有其他方法,又写了10分钟33:大模型相关问题,agent,Transfomer34:反问全称1小时40分钟,汗流浃背,后面写SQL的时候脑子已经不转了。二面4月15日1:深挖项目(20分钟)2:Redission怎么实现的?3:为什么不用redis的setnx?4:数据库分库分表,分库分表会有什么问题?(说了一下怎么分库分表,有什么问题没打上来)5:某个服务器cpu飙高怎么排查(top,htop,ps,&nbsp;jstake,&nbsp;dump文件,visualVM)6:优化sql?(skywalking,慢查询日志,索引,elplain的字段)7:深度分页优化?(业务上不允许深度分页,子查询,索引查询,游标分页)反问#牛客AI配图神器#二面完,感觉g了,面试官说项目没选好,mysql没有分库,不太像分布式项目。
这名字响亮不响亮:我去,spring是你简历写的熟悉源码嘛,还是面试官直接问的嗷。好可怕
点赞 评论 收藏
分享
评论
5
38
分享

创作者周榜

更多
牛客网
牛客企业服务