• 关于面试-java面试题汇总


    项目介绍

    大部分情况,这是一场面试的开门题,面试官问这个问题,主要是考察你的概述能力和全局视野。有的人经常抱怨自己每天在堆业务,但没有成长。事实上,很多情况下确实在堆业务,但并不是没有成长的。并非做中间件或者技术架构才是成长,例如我们的需求分析能力,沟通协作能力,产品思维能力,抽象建模能力等都是一个非常重要的硬实力。

    Java基础

    1、List 和 Set 的区别

    1:List:可重复,有序,数组或者链表存储
    
    2:Set:不可重复,无序,使用map存储
    
    • 1
    • 2
    • 3

    2、HashSet 是如何保证不重复的

    (1)如果hash码值(hashcode())相同,且equles判断相等,说明元素已经存在,不存;
    
    (2)如果hash码值(hashcode())相同,且equles判断不相等,说明元素不存在,存;
    
    • 1
    • 2
    • 3

    3、HashMap 是线程安全的吗,为什么不是线程安全的(最好画图说明多线程环境下不安全)?

        1. 对象不能安全发布,构造过程逃逸; 
    
        2. 内存的可见性,内容不能及时发布;
    
        3. 操作不是原子的; 
    
        4. 读写不能同步;
    
        5. 存在死锁的可能性;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    4、HashMap 的扩容过程

       HashMap的初始容量都是2的n次幂的形式存在的,而扩容也是2倍的原来的容量进行扩容
    
    • 1

    5、HashMap 1.7 与 1.8 的 区别,说明 1.8 做了哪些优化,如何优化的?

      (1) 1.7的jdk采用Entry数组来存储数据,但是entry是链表结构。在数据量大的情况下,put/get操作时间会略长。
    
      (2) 1.8的jdk采用node数组存储数据,node采用链表+红黑树结构,那么当数据存储在数组格子里,且这个格子key超过8个,会把链表转换为红黑树。那么根据红黑树的特性,在大数据量put/get会跟快。
    
    • 1
    • 2
    • 3

    6、HashMap实现原理 ?

        HashMap是基于hashing的原理,使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket位置来储存Entry对象。
    
    • 1

    hashmap原理:

        操作put时,初始化好并查询链表长度是否需要扩容(扩容2倍),在根据key求hash值在计算它的下标做存储。 如果链表长度超过阈值,就会扩容成红黑树。
    
        操作get时,使用键的hashcode求取bucket位置,在找到节点并返回。
    
    • 1
    • 2
    • 3

    ConcurrentHashMap(安全):

              (1)JDK1.7里面,ConcurrentHashMap是用Segment和HashEntry实现的,每个Segment都是继承于Reentrantlock的,在对该segment进行操作时,获取锁,结束操作释放锁。
    
              (2)JDK1.8里面,没有用segment,而是用Node+CAS+synchronized实现的。
    
    • 1
    • 2
    • 3

    HashMap(不安全,存在死锁可能性):默认16,扩容是2倍,一个Entry数组,当发生hash冲突的时候,hashmap是采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结点加入。

    (1) 1.7的jdk采用Entry数组来存储数据,但是entry是链表结构。在数据量大的情况下,put/get操作时间会略长。

    (2) 1.8的jdk采用node数组存储数据,node采用链表+红黑树结构,那么当数据存储在数组格子里,且这个格子key超过8个,会把链表转换为红黑树。那么根据红黑树的特性,在大数据量put/get会跟快。

    7、HashMap 的并发问题?

        HashMap在多线程put后可能导致get无限循环 。
    
        如果扩容前相邻的两个Entry在扩容后还是分配到相同的table位置上,就会出现死循环的BUG。
    
        解决方案:
    
            使用ConcurrentHashMap进行替代
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    8、Java反射

        java 获取反射常使用的三种方式:
    
            1.通过new对象实现反射机制
    
            2.通过路径实现反射机制
    
            3.通过类名实现反射机制
    
    //方式一(通过建立对象)
    Student stu = new Student();
    Class classobj1 = stu.getClass();
    System.out.println(classobj1.getName());
    	
    //方式二(所在通过路径-相对路径)
    Class classobj2 = Class.forName("fanshe.Student");
    System.out.println(classobj2.getName());
    	
    //方式三(通过类名)
    Class classobj3 = Student.class;
    System.out.println(classobj3.getName());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    Java 并发

    1、synchronized 的实现原理以及锁优化?

        synchronized 常见的三种用法如下:
    
            普通同步方法,锁是当前实例对象
    
            静态同步方法,锁是当前类的class对象
    
            同步方法块,锁是括号里面的对象
    
    
    
       synchronized的对象锁,其指针指向的是一个monitor对象(由C++实现)的起始地址。每个对象实例都会有一个 monitor。其中monitor可以与对象一起创建、销毁;亦或者当线程试图获取对象锁时自动生成。需要注意的是monitor不是Java特有的概念.
    
    实现原理:
    
        每个对象有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:
    
        如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。
    
        如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1。
    
        如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2、volatile 的实现原理?

        1.保证共享变量可见性
    
            通俗来说就是,某个线程对一个volatile变量的修改,对于其它线程来说是可见的,即线程每次获取volatile变量的值都是最新的。
    
        2.禁止指令重排序
    
            volatile底层通过内存屏障实现禁止特定类型的处理器重排序
    
        原理:操作发送一个lock前缀的命令并写到系统内存,当其他线程来获取,效验这个lock,不对就重新获取值。(类似版本锁)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3、Java 的信号灯?

        Semaphore是Java1.5之后提供的一种同步工具,Semaphore可以维护访问自身线程个数,并提供了同步机制。使用Semaphore可以控制同时访问资源的线程个数,通过 acquire() 获取一个许可,如果没有就等待,而release() 释放一个许可。
    
    • 1

    4、synchronized 在静态方法和普通方法的区别?

        synchronized修饰不加static的方法,锁是加在单个对象上,不同的对象没有竞争关系;
    
        synchronized修饰加了static的方法,锁是加载类上,这个类所有的对象竞争一把锁。
    
    • 1
    • 2
    • 3

    5、怎么实现所有线程在等待某个事件的发生才会去执行?

        1.使用读写锁,刚开始主线程先获取写锁,然后所有子线程获取读锁,然后等事件发生时主线程释放写锁;
    
        2.使用CountDownLatch,初始值设为1,所有子线程调用await方法等待,等事件发生时调用countDown方法计数减为0;
    
    • 1
    • 2
    • 3

    6、CAS?CAS 有什么缺陷,如何解决?

        Cas是另一个无锁解决方案,更准确的是采用乐观锁技术,实现线程安全的问题。cas有三个操作数----内存对象(V)、预期原值(A)、新值(B)。
    
       CAS缺点这个方式也存在一定的问题:
    
                1、自循环时间长,开销大
    
                2、只能保证一个共享变量的原子操作
    
                3、ABA问题
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    7、synchronized 和 lock 有什么区别?

        1.Lock是一个接口,而synchronized是关键字。
    
        2.synchronized会自动释放锁,而Lock必须手动释放锁。
    
        3.Lock可以让等待锁的线程响应中断,而synchronized不会,线程会一直等待下去。
    
        4.通过Lock可以知道线程有没有拿到锁,而synchronized不能。
    
        5.synchronized能锁住类、方法和代码块,而Lock是块范围内的
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    8、final finally finalize

        final 表示最终的、不可改变的。用于修饰类、方法和变量。
    
        finally 异常处理的一部分,它只能用在try/catch语句中,表示希望finally语句块中的代码最后一定被执行(但是不一定会被执行)
    
        finalize()是在java.lang.Object里定义的,Object的finalize方法什么都不做,对象被回收时finalized方法会被调用。
    
        特殊情况下,可重写finalize方法,当对象被回收的时候释放一些资源。但注意,要调用super.finalize()。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    9、强引用 、软引用、 弱引用、虚引用

          强引用: 是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。
    
          软引用: 如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;
    
          弱引用: 与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期 
    
          虚引用: 顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    image.png

    10、ConcurrenHashMap 介绍?1.8 中为什么要用红黑树?

        ConcurrenHashMap 是当hash值相同的情况下(大于8),才会采用红黑树,利用红黑树的二分查找法进行定位。性能较高。
    
    • 1

    11、ThreadLocal原理,用的时候需要注意什么?

        ThreadLocal是并发场景下用来解决变量共享问题的类,它能使原本线程间共享的对象进行线程隔离,即一个对象只对一个线程可见。
    
        需要注意的是,threadlocal在多线程下并不是线程安全的。
    
    • 1
    • 2
    • 3

    12、如何检测死锁?怎么预防死锁?

        通过jvisualvm查看产生的死锁线程,一步步排查。 
    
        预防死锁可以设置加锁顺序,设置加锁时限等方法。
    
    • 1
    • 2
    • 3

    13、Java 内存模型?

        程序计数器
    
        堆
    
        栈
    
        方法区
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    14、线程池的种类,区别和使用场景?

        四种线程池:
    
            1. newCachedThreadPool(缓存)
    
            2. newFixedThreadPool(单线程)
    
            2. newScheduledThreadPool(定长)
    
            4.newSingleThreadExecutor(延迟)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Spring

    1、BeanFactory 和 FactoryBean?

            BeanFactory只是个接口,负责生产和管理bean,它为其他具体的IOC容器提供了最基本的规范。
    
            FactoryBean是一个接口,当在IOC容器中的Bean实现了FactoryBean后,通过getBean获取到的Bean对象并不是FactoryBean的实现类对象,而是这个实现类中的getObject()方法返回的对象。
    
    • 1
    • 2
    • 3

    2、Spring IOC 的理解,其初始化过程?

        ioc即依赖注入,就是把某某托管给这个工厂去创建,并实现。
    
        初始化流程:
    
            1.Resource定位,读取xml获取对应加载类的路径获取主要注入的接口类。
    
            2.加载到spring的容器里。
    
            3.注册对应的接口类,并存到容器里。(map里)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3、BeanFactory 和 ApplicationContext?

        BeanFactory只是个接口,负责生产和管理bean,它为其他具体的IOC容器提供了最基本的规范。
    
        ApplicationContext是负责加载上下文或读取资源文件的类,或者通过他去实例化bean。
    
    • 1
    • 2
    • 3

    4、Spring Bean 的生命周期,如何被管理的?

        1.创建bean
    
        2.set方法注入
    
        3.调用init方法bean初始化
    
        4.执行初始化方法
    
        5.销毁
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    5、如果要你实现Spring AOP,请问怎么实现?

    6、如果要你实现Spring IOC,你会注意哪些问题?

    7、Spring 是如何管理事务的,事务管理机制?

        Spring事务管理模块主要包括3个接口:
    
            PlatformTransactionManager:事务管理器,主要用于平台相关的事务管理。
    
            TransactionDefinition:事务定义信息(隔离级别、传播、超时、只读)通过配置如何进行事务管理。
    
            TransactionStatus:事务具体运行状态——事务管理过程中,每个时间点事务的状态信息。
    
        主要通过这三个接口来实现aop切面,对事务做管理。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    8、Spring 的不同事务传播行为有哪些,干什么用的?

       这里写图片描述
    
    • 1

    9、Spring 中用到了那些设计模式?

        工厂,单例,模型,原型,适配器,策略,装饰者。
    
    • 1

    Springboot

    boot如何自动装配和启动流程是怎么样的?

      首先启动会先找到run方法,run方法会找到SpringBootApplication注解,里面包含三个注解,然后简单说一下每个注解的作用.
    
      1.SpringApplication.run 执行流程中有refreshContext(context),内部会解析我们的配置类上的标签,实现自动装配功能的注解@EnableAntoConfiguration
    
      2.会解析@EnableAntoConfiguration这个注解里面的@Import引入的配置类@AntoConfigurationImportSelector
    
      3.@AntoConfigurationImportSelector这个类中有方法SpringFactoriesLoder.loadFactoryNames(getStringFactoriesLoaderFactoryClass(),getBeanClasLoader());作用就是读取jarbao中的项目中的META-INF/spring.factories文件
    
      4.spring.factories 配置了要自动装配的 Configuration 类。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    什么是 Spring Boot Stater ?

    starter负责配置好与spring整合相关的配置和相关依赖(jar和jar版本),使用者无需关心框架整合带来的问题。
    
    • 1

    Netty

    1、BIO、NIO和AIO

    2、Netty 的各大组件

    3、Netty的线程模型

    4、TCP 粘包/拆包的原因及解决方法

    5、了解哪几种序列化协议?包括使用场景和如何去选择

    6、Netty的零拷贝实现

    7、Netty的高性能表现在哪些方面

    分布式相关

    1、Dubbo的底层实现原理和机制

        Dubbo :是一个rpc框架,soa框架
    
        作为RPC:支持各种传输协议,如dubbo,hession,json,fastjson,底层采用mina,netty长连接进行传输!典型的provider和cusomer模式!
    
         作为SOA:具有服务治理功能,提供服务的注册和发现!用zookeeper实现注册中心!启动时候服务端会把所有接口注册到注册中心,并且订阅configurators,服务消费端订阅provide,configurators,routers,订阅变更时,zk会推送providers,configuators,routers,启动时注册长连接,进行通讯!proveider和provider启动后,后台启动定时器,发送统计数据到monitor!提供各种容错机制和负载均衡策略!!
    
        Dubbo的实现:
    
        Dubbo协议的Invoker转为Exporter发生在DubboProtocol类的export方法,它主要是打开socket侦听服务,并接收客户端发来的各种请求,通讯细节由Dubbo自己实现。
    
        dubbo原理:
    
            I.初始化过程
    
            2.解析服务
    
            3.暴露服务
    
            4.引用服务
    
        dubbo的泛化调用:泛化接口调用方式主要用于客户端没有 API 接口(泛化调用是指不需要依赖服务的二方包)及模型类元的情况,参数及返回值中的所有 POJO 均用 Map 表示,通常用于框架集成,API网关比如:实现一个通用的服务测试框架,可通过 GenericService 调用所有服务实现。泛化调用的方式可以有效减少平台型产品的二方包依赖,实现系统的轻量级运行。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2、描述一个服务从发布到被消费的详细过程

        首先先获取zk的配置信息,然后获取需要生产者暴露的url,然后调用registry.register方法将url注册到zookeeper上去,然后去消费者配置对应配置,根据端口和接口到注册中心找到生产者接口,然后去调用。
    
    • 1

    3、分布式系统怎么做服务治理

        服务治理解决方案:负载均衡,熔断降级限流,链路追踪,服务发现与配置中心,连接复用
    
        服务治理的痛点:超时配置,线程池配置,故障定位
    
    • 1
    • 2
    • 3

    4、幂等性的概念

        一个操作重复执行多次,其效果(不考虑操作时间)和只执行一次是一样的,那么这个操作就叫做是幂等
    
    • 1

    5、消息中间件如何解决消息丢失问题

        以rabbitmq为例:
    
            消息持久化:RabbitMQ 的消息默认存放在内存上面,如果不特别声明设置,消息不会持久化保存到硬盘上面的,如果节点重启或者意外crash掉,消息就会丢失。
    
            需要做到消息持久化,以下三个条件缺一不可。
    
                Exchange设置持久化
    
                Queue设置持久化 
    
                Message设置持久化    
    
            ack确认机制:就是消费端消费完成要通知服务端,服务端才把消息从内存删除。
    
        RabbitMQ消息丢失解决方案:
    
            第一步:设置创建queue设置为持久化(只会持久化queue元数据,但不会持久化queue中的数据);
    
            第二步:发送消息时,设置deliveryMode设置为2(此时queue中的数据也将被持久化);
    
            第三步:配合confirm机制使用(推荐使用异步监听机制,不推荐事务机制),当消息被持久化后才通知生产者ack;
    
        RabbitMQ消费者丢失数据场景:
    
            消费者接收到消息,但是还没操作,消费者自己挂了,但是rabbitmq以为该条消息已经被消费.
    
        消费者丢失数据解决方案:
    
            将autoAck关闭,在处理完消息后再手动提交ack;    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    6、Dubbo的服务请求失败怎么处理

        重连或者配置超时请求
    
    • 1

    7、重连机制会不会造成错误

        如果在高性能请求的环境下,会导致服务雪崩。
    
    • 1

    8、对分布式事务的理解

        分布式事务就是指事务的参与者、支持事务的服务器分布于不同服务器节点上,要保证这些小操作要么全部成功,要么全部失败
    
    • 1

    9、如何实现负载均衡,有哪些算法可以实现?

        轮询法、随机法、源地址哈希法、加权轮询法、加权随机法、最小连接法
    
    • 1

    10、Zookeeper的用途,选举的原理是什么?

        zk的用途:1.命名服务 2.配置管理 3.集群管理 4.分布式锁 
    
        选举原理:当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的Server都恢复到一个正确的状态。
    
                        1.选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server;
    
                        2.选举线程首先向所有Server发起一次询问(包括自己);
    
                        3.举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中;
    
                         4. 收到所有Server回复以后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server;
    
                         5.线程将当前zxid最大的Server设置为当前Server要推荐的Leader,如果此时获胜的Server获得n/2 + 1的Server票数, 设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置自己的状态,否则,继续这个过程,直到leader被选举出来。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    11、数据的垂直拆分水平拆分。

        垂直拆分:把一个拥有很多列的表拆分为多个表,原则根据使用度的区分,根据业务区分,根据复杂类型区分
    
        水平拆分:指按照业务对系统进行划分 。
    
    • 1
    • 2
    • 3

    12、zookeeper原理和适用场景

        zookeeper基本原理:树形层次结构,树中的节点称为 Znode, 每个 Znode 存储的数据有小于 1m 的大小限制。zookeeper 对 Znode 提供了几种类型:临时 Znode、持久 Znode、顺序 node 等几种类型,用于不同的一致性需求。在 Znode 发生变化时,通过“观察”(watch)机制可以让客户端得到通知。可以针对 Zookeeper 服务的“操作”来设置观察,该服务的其他操作可以触发观察。Zookeeper 服务的“操作”包括一些对 Znode 添加修改获取操作。
    
        zookeeper适用场景:可以用作集群管理,服务名统一管理,配置管理等。
    
    • 1
    • 2
    • 3

    13、zookeeper watch机制

        Znode发生变化(Znode本身的增加,删除,修改,以及子Znode的变化)可以通过Watch机制通知到客户端
    
    • 1

    14、redis/zk节点宕机如何处理

            redis根据哨兵机制处理。
    
            zk根据心跳机制检测做轮询重新选举。
    
    • 1
    • 2
    • 3

    15、分布式集群下如何做到唯一序列号

        数据库id,uuid,雪花算法等方式去生成唯一序列号
    
    • 1

    16、如何做一个分布式锁

        可以使用redis来实现,当有一个商品下单,生成key签名,并把对应商品采用redis提供的锁做锁定,并设置时限,如果超出时间其他线程可下单。
    
    • 1

    17.b和b+树的区别

        b树:
    
        b+树:
    
        区别:主要是存储的内容不一样,b树只存单一数据,b+可以存储hash集合等。检索查询的方式不一样,b是一层层遍历,b+顺序排列相连。
    
    • 1
    • 2
    • 3
    • 4
    • 5

    缓存

    1、Redis有过哪些数据,以及Redis底层怎么实现

        五种类型:(string)字符串对象,(list)列表对象,(hash)哈希对象,(set)集合对象,(zset)有序集合对象
    
          底层实现:
    
            1.String的底层实现:string原理
    
            底层字符串特性?
    
                 1).二进制安全(体现在len这个字段上)
    
                 2).避免频繁的内存分配,进行内存得预分配(体现在上面扩容过程)
    
                 3).兼容c语言函数库(其实底层都会加\0占一个字节作为字符串结尾)
    
            
    
            2.哈希底层的实现:数组 + 链表(采用头插法解决冲突,不会像java语言的map一样转化为红黑树),redis会把kay、value封装成一个dictEntry的结构体(dictEntry的key为string类型,value是一个指针,指向一个redisObject对象(不像java语言一样把hashmap的key、value的具体值封装在一起))
    
                  redis为什么要把value封装成一个redisObject对象?
    
                  因为redis支持value的值有多种不同的数据类型
    
            3.list底层实现:底层是链表,有两个list,一个是ziplist,字面意是压缩列表,另一个是quicklist,字面意是快速列表,在redis中直接使用的是quicklist
    
            4.set底层实现: Set是一个特殊的value为空的Hash。
    
            5.zset底层实现:Zset底层是一种跳表SkipList数据结构(跳表在原有的有序链表上面增加了多级索引,通过索引来实现快速查找,实质就是一种可以进行二分查找的
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    2、Redis缓存穿透,缓存雪崩

    缓存穿透问题

    现象:用户大量并发请求的数据(key)对应的数据在redis和数据库中都不存在,导致尽管数据不存在但还是每次都会进行查DB。

    为什么key对应数据在缓存和db中不存在还会每次都进行DB查询呢?因为很多开发同学写的代码写的逻辑都是先从redis缓存中查一把,如果缓存中为空则从DB中查,如果DB中查到的数据不为空则设置到缓存并返回给接口。那么问题来了,如果从DB中查询的数据为空呢??

    解决方案:

    从DB中查询出来数据为空,也进行空数据的缓存,避免DB数据为空也每次都进行数据库查询;
    
    使用布隆过滤器,但是会增加一定的复杂度及存在一定的误判率;
    
    • 1
    • 2
    • 3

    缓存雪崩问题

    现象:大量key同一时间点失效,同时又有大量请求打进来,导致流量直接打在DB上,造成DB不可用。

    解决方案:

    设置key永不失效(热点数据);

    设置key缓存失效时候尽可能错开;

    使用多级缓存机制,比如同时使用redsi和memcache缓存,请求->redis->memcache->db;

    3、如何使用Redis来实现分布式锁

    4、Redis的并发竞争问题如何解决

    5、Redis持久化的几种方式,优缺点是什么,怎么实现的

    6、Redis的缓存失效策略

    7、Redis集群,高可用,原理

    8、Redis缓存分片

    9、Redis的数据淘汰策略

    JVM

    1、详细jvm内存模型

    2、讲讲什么情况下回出现内存溢出,内存泄漏?

    3、说说Java线程栈

    4、JVM 年轻代到年老代的晋升过程的判断条件是什么呢?

    5、JVM 出现 fullGC 很频繁,怎么去线上排查问题?

    6、类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式?

    7、类的实例化顺序

    8、JVM垃圾回收机制,何时触发MinorGC等操作

    9、JVM 中一次完整的 GC 流程(从 ygc 到 fgc)是怎样的

    10、各种回收器,各自优缺点,重点CMS、G1 11、各种回收算法

    12、OOM错误,stackoverflow错误,permgen space错误

    1)put的时候导致的多线程数据不一致。

    这个问题比较好想象,比如有两个线程A和B,首先A希望插入一个key-value对到HashMap中,首先计算记录所要落到的桶的索引坐标,然后获取到该桶里面的链表头结点,此时线程A的时间片用完了,而此时线程B被调度得以执行,和线程A一样执行,只不过线程B成功将记录插到了桶里面,假设线程A插入的记录计算出来的桶索引和线程B要插入的记录计算出来的桶索引是一样的,那么当线程B成功插入之后,线程A再次被调度运行时,它依然持有过期的链表头但是它对此一无所知,以至于它认为它应该这样做,如此一来就覆盖了线程B插入的记录,这样线程B插入的记录就凭空消失了,造成了数据不一致的行为。

    2)另外一个比较明显的线程不安全的问题是HashMap的get操作可能因为resize而引起死循环(cpu100%)

    java

    1.基础(集合,io流)-----》进阶:多线程包,JVM,设计模式

    2.spring(ioc和aop)-----》进阶:事务,分布式事务

    3.中间件(zookeeper,redis,activemq)集群-----》落地:缓存穿透,雪崩

    4.RPC框架(dubbo,Cloud)----》问题:dubbo和cloud的区别

    5.接口(http,webservice)

    数据库

    1.mysql,oracle(特性与区别)

    2.acid原理

    3.数据库4种隔离级别

    4.数据库优化(执行计划解析,索引的场景,索引碎片的处理)

    5.分区分表

    流程图、甘特图、燃尽图

    项目风险时间控制

    懂点技术

    然后让下面人 乐意 跟你干

    前端

    1.html

    2.css

    3.js

    4.es6,webpack

    5.vue,react

    如果技术点的话,有:

    1.前后加密双重效验实现机制

    2.单点登录实现原理和几种方式

    3.跨域怎么实现互通手段和几种方式

    4.nio,bio的区别和机制

    5.消息中间件的原理,举例你用的几项

    6.sql优化和执行计划的技巧使用过么

    7.java并发编程的有几个类,并举例几个常见的并发设计模式

    参考:面试宝典

    https://gitee.com/MrString/study

  • 相关阅读:
    如何制作专属的VS Code主题
    java毕业设计户籍管理系统(附源码、数据库)
    云原生之使用Docker部署Nas-Cab个人NAS平台
    【项目SpringBoot配置详解】
    java使用jol打印对象信息
    JAVA 反序列化之 Apache Commons Collections 反序列化漏洞分析
    什么是泛型,什么是泛型约束
    Salesforce action function调用不到的解决方式
    今日来介绍关于淘宝相似商品搜索的API接口
    字节面试官:你觉得TCP 为什么要三次握手呢?
  • 原文地址:https://blog.csdn.net/qq_20057315/article/details/128202705