当前位置: 首页 > article >正文

八股+面经

文章目录

  • 项目介绍
    • 1.不动产项目
      • 数据
      • 机器学习算法调研
      • 图像提取算法调研
        • 数据集-ImageNet
        • Xception
        • VGG
        • Inception
        • Densenet
        • Mobilenet
    • 2.图书项目
      • 技术栈
      • 面试问题
  • Java基础
    • 反射
    • 接口和抽象类
    • Map
      • HashMap v.s Hashtable(5点)
      • ConcurrentHashMap v.s Hashtable(2点)
      • 代理模式
        • 1. 静态代理
        • 2. 动态代理
        • 2.1 JDK 动态代理机制
        • 2.2 CGLIB 动态代理机制
        • 2.3 二者对比
  • Java并发
    • 并发编程三个重要特性
    • 线程
        • **创建线程的三种方式**
        • 多线程
        • 生命周期&状态
        • 上下文切换
        • sleep()和wait()
    • volatile
      • 如何保证变量的可见性?
      • 如何禁止指令重排序?
      • volatile 可以保证原子性么?
    • synchronized
      • 1. 使用场景
      • 2. 底层原理
        • synchronized 同步语句块
        • synchronized 修饰方法
      • 3. 和volatile区别
    • ReentrantLock
        • 和synchronized区别
    • AQS
    • 线程池
      • 1. 线程池作用
      • 2. 创建线程池方法
      • 3. 线程池饱和策略
      • 4. 常用阻塞队列
      • 5. 线程池处理任务流程
      • 6. 线程池大小
  • JVM
    • 类加载机制
    • 垃圾回收(GC)
      • 1. 引用类型
      • 2. 垃圾收集
      • 3. 垃圾回收算法(内存回收方法论)
      • 4. 垃圾收集器(内存回收具体实现)
        • **Serial:**
        • **ParNew:**
        • **Parallel Scavenge:**
        • **Serial Old**
        • **Parallel Old**
        • **CMS**
        • **G1**(Garbage-First)
        • 总结
  • 设计模式
    • 单例模式
  • MySQL
    • 存储引擎
    • 索引
      • 1. 优缺点
      • 2. 底层数据结构
        • B&B+树
      • 3. 索引类型总结
    • 事务
      • 1. ACID
      • 2. 并发事务问题
      • 3. 并发事务控制方式
        • MVCC
      • 4. 隔离级别
    • 锁机制
    • MVCC
      • RC和RR下 MVCC 的差异
  • Redis
    • 为什么用redis做mysql缓存?
    • 数据结构
        • 常见数据结构
        • 底层数据结构
    • 线程模型
        • 1. 单线程模式
        • 2. 单线程 v.s 多线程
    • 缓存读写策略
      • 1. 旁路缓存模式
      • 2. 读写穿透
      • 3. 异步缓存写入
    • 持久化
      • AOF日志
      • RDB快照
    • 过期删除&内存淘汰策略
      • 过期删除
  • 计算机网络
    • HTTP与HTTPS
    • HTTP/1.0 和 HTTP/1.1 和 HTTP/2.0
    • 三次握手(建立TCP连接)
    • 四次挥手(断开TCP连接)
    • TCP v.s UDP
    • DNS(域名IP映射)
  • 操作系统
  • Spring
    • IoC
    • AoP
  • 银行
  • 面试题目
    • 1. 拼多多 3.23
    • 2. 美团-履约 3.24
    • 3. 联想 3.27
    • 4. 蚂蚁-数金 3.28
    • 5. 美团-酒旅 3.30
    • 6. 快手-海外业务 4.20
    • 7. 邮储-北京 4.25
    • 8. 阿里-ICBU 4.26
    • 9. 字节-4.28
    • 7. 邮储-北京 4.25
    • 8. 阿里-ICBU 4.26
    • 9. 字节-4.28

项目介绍

1.不动产项目

在这里插入图片描述

数据

机器学习算法调研

12种基学习器,评价指标为RMSE、MAE、MAPE和R2,最终选定Catboost和LightGBM

image-20230404160403504

图像提取算法调研

数据集-ImageNet

Xception

论文:Xception: Deep Learning with Depthwise Separable Convolutions (CVPR 2017)

源码:Keras开源代码

VGG

Very Deep Convolutional Networks for Large-Scale Image Recognition

Inception

Densenet

Mobilenet

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yBRgQoyn-1682664727877)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20230419190536360.png)]

2.图书项目

JPA和Mybatis区别

技术栈

前端服务器Nginx后端服务器Tomcat,开发前端内容时,可以把前端的请求通过前端服务器转发给后端(称为反向代理

在这里插入图片描述

用户信息明文存储在数据库中,不安全

shiro

三大概念

  • Subject:负责存储与修改当前用户的信息和状态
  • SecurityManager:安全相关的操作实际上是由她管理的
  • Realms:负责从数据源中获取数据并加工后传给 SecurityManager

四大功能

  • Authentication(认证)
  • Authorization(授权)
  • Session Management(会话管理)
  • Cryptography(加密)

面试问题

  1. Spring Security和Shiro的区别?

    • Shiro比Spring更容易使用,实现和理解
    • Shiro 功能强大、且 简单、灵活
    • Shiro是 Apache 下的项目,比较可靠,不跟任何的框架或者容器绑定,可以独立运行
  2. 项目中redis用什么客户端部署?

    • Java 访问 Redis 主要是通过 JedisLettuce 两种由不同团队开发的客户端(提供访问、操作所需的 API),Jedis 比较原生,Lettuce 提供的能力更加全面

    • 本项目用Spring Data Redis,Spring Data Redis是在 Lettuce 的基础上做了一些封装,与 Spring 生态更加贴合,使用起来也更简便。

  3. java怎么连接数据库?

    配置maven依赖->配置数据库(application.properties)

延时双删:先清除缓存,在更新数据库后,等一段时间,再去第二次执行删除操作。

Java基础

反射

反射就是把java类中的各种成分映射成一个个的Java对象

接口和抽象类

共同点

  • 都不能被实例化。
  • 都可以包含抽象方法。
  • 都可以有默认实现的方法(default关键字)

区别

  • 接口主要用于对类的行为进行约束,你实现了某个接口就具有了对应的行为。抽象类主要用于代码复用,强调的是所属关系。
  • 一个类只能继承一个类,但是可以实现多个接口。
  • 接口中的成员变量只能是 public static final 类型的,不能被修改且必须有初始值,而抽象类的成员变量默认 default,可在子类中被重新定义,也可被重新赋值。

Map

HashMap

image-20230426152542432

HashMap v.s Hashtable(5点)

在这里插入图片描述

ConcurrentHashMap v.s Hashtable(2点)

  1. 底层数据结构不同
在这里插入图片描述
  1. 实现线程安全方式不同
在这里插入图片描述

代理模式

1. 静态代理

针对每个目标类都单独创建一个代理类

2. 动态代理

从 JVM 角度来说,动态代理是在运行时动态生成类字节码,并加载到 JVM 中的。

Spring AOP、RPC框架的实现依赖动态代理

  • 2.1 JDK 动态代理机制

    • InvocationHandler 接口和 Proxy 类是核心
  • 2.2 CGLIB 动态代理机制

    • JDK 动态代理有一个最致命的问题是其只能代理实现了接口的类。为了解决这个问题,我们可以用 CGLIB 动态代理机制来避免。
    • 在 CGLIB 动态代理机制中 MethodInterceptor 接口和 Enhancer 类是核心。
  • 2.3 二者对比

    • 灵活性 :动态代理更加灵活,不需要必须实现接口,可以直接代理实现类,并且可以不需要针对每个目标类都创建一个代理类。另外,静态代理中,接口一旦新增加方法,目标对象和代理对象都要进行修改,这是非常麻烦的!
    • JVM 层面 :静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的 class 文件。而动态代理是在运行时动态生成类字节码,并加载到 JVM 中的。

Java并发

并发编程三个重要特性

  1. 原子性

    含义:一次操作或者多次操作,要么所有的操作全部都得到执行并且不会受到任何因素的干扰而中断,要么都不执行。

    Java实现:synchronized 、各种 Lock 以及各种原子类

    synchronized 和各种 Lock 可以保证任一时刻只有一个线程访问该代码块,因此可以保障原子性。各种原子类是利用 CAS (compare and swap) 操作(可能也会用到 volatile或者final关键字)来保证原子操作。

  2. 可见性

    含义:一个线程对共享变量进行修改,另外的线程立即可以看到修改后的最新值。

    Java实现:synchronizedvolatile 以及各种 Lock

  3. 有序性

    含义:代码的执行顺序未必就是编写代码时候的顺序。

    Java实现:volatile 关键字可以禁止指令进行重排序优化

线程

  • 什么是线程?
    • 比进程更小的执行单位
    • 线程切换工作时负担比进程小得多
  • 进程和线程的区别
    • 在这里插入图片描述
    • 进程可以有多个线程,同类的多个线程共享进程的方法区资源,每个线程有自己的程序计数器、虚拟机栈本地方法栈
    • 各进程是独立的,同一进程中的线程可能会互相影响
    • 线程执行开销小,但不利于资源的管理和保护;进程相反
  • 为啥程序计数器是私有的?
    • 为了线程切换后能恢复到正确的执行位置
  • 为啥虚拟机栈和本地方法栈私有?
    • 为了保证线程中的局部变量不被别的线程访问到
  • 堆和方法区了解
    • 堆是进程中最大的一块内存,主要用于存放新创建的对象

创建线程的三种方式

  • 1、继承Thread类

    • 重写run方法,start()启动
    class MyThread extends Thread{
      @Override
      public void run(){
        System.out.println("这是重写的run方法,也叫执行体");
        System.out.println("线程号:" + currentThread().getName());
      }
    }
    
    public class Test{
      public static void main(String[] args) throws Exception{
        Thread t1 = new MyThread();
        t1.start();
      }
    }
    
    
    • 优点:简单,访问当前现线程直接使用currentThread()
    • 缺点:继承Thread类,无法继承其他类
  • 2、实现Runable接口

    class MyThread implements Runable{
      @Override
      public void run(){
        System.out.println("这是重写的run方法,也叫执行体");
        System.out.println("线程号:" + Thread.currentThread().getName());
      }
    }
    
    public class Test{
      public static void main(String[] args) throws Exception{
        MyThread myThread = new MyThread();
        Thread t1 = new Thread(myThread);
        t1.start();
      }
    }
    
    • 优点:可以继承别的类,多个线程共享一个对象,适合处理同一份资源的情况
    • 缺点:访问当前线程需要使用Thread.currentThread()
  • 3、Callable接口:

    • 实现Callble接口,重写call()方法,作为执行体;
    • 创建实现类的实例,用FutureTask包装;
    • 使用FutureTask对象作为Thread对象创建线程;
    • 使用FutureTask对象的get()方法获得子线程执行结束后的返回值
    class MyThread implements Callable{
      @Override
      public Object call() throws Exception{
        System.out.println("线程号:" + Thread.currentThread().getName());
        return 10;
      }
    }
    
    public class Test{
      public static void main(String[] args) throws Exception{
        Callable callable = new MyThread();
        FutureTask task = new FutureTask(callable);
        new Thread(task).start();
        System.out.println(task.get());
        Thread.sleep(10);//等待线程执行结束
        //task.get() 获取call()的返回值。若调用时call()方法未返回,则阻塞线程等待返回值
        //get的传入参数为等待时间,超时抛出超时异常;传入参数为空时,则不设超时,一直等待
        System.out.println(task.get(100L, TimeUnit.MILLSECONDS));
      }
    }
    
  • Runnable和Callable的区别:

    • Callable规定的方法是call(),Runnable规定的方法是run().
    • Callable的任务执行后可返回值,而Runnable的任务是不能返回值得
    • call方法可以抛出异常,run方法不可以,因为run方法本身没有抛出异常,所以自定义的线程类在重写run的时候也无法抛出异常
    • 运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
  • start()与run()的区别

    • start用于启动线程,线程处于就绪状态,直到得到CPU时间片才运行,再自动执行run方法;
    • run方法只是类的普通方法,直接调用相当于只有主线程一个线程;
  • sleep() 与 wait() 与 join() 与 yield():

    • 作用:sleep()与wait()都可以暂停线程执行
      • sleep:线程让出CPU资源,不会释放锁
      • wait:线程让出CPU, 释放锁;与notify(), notifyAll() 一起使用
        • 基于哨兵思想:检查特定条件直到满足,才继续进行
          • 需要监视器监视当前线程:如synchronized, Condition类
        • notify:随机唤醒单个线程
        • notifyAll:唤醒所有线程
      • yield:暂停当前线程,给其他具有相同优先级的线程(包括自己)运行的机会
      • join:让主线程等待子线程结束之后在结束; 比如需要子线程的运行结果的时候,由子线程调用;
    • sleep 和 yield 是Thread的静态方法; join是线程对象调用; wait, notify, notifyAll 是Object类的方法,所有对象都可以调用。

多线程

  • 为什么使用多线程?
    • 总体上
      • 计算机底层:线程切换调度成本小于进程;多核CPU->多个线程可以同时运行,减少上下文切换开销
      • 互连网发展趋势:多线程是高并发系统的基础,可以提高系统整体的并发能力和性能
    • 计算机底层
      • 单核时代:提高单进程利用CPU和IO系统的效率,一个线程IO阻塞,其他线程还能用CPU
      • 多核时代:提高进程利用多核CPU的能力
  • 多线程带来的问题?
    • 内存泄露、死锁、线程不安全

生命周期&状态

六个状态:

  1. NEW: 初始状态,线程被创建出来但没有被调用 start()

  2. RUNNABLE: 运行状态,线程被调用了 start()等待运行的状态。

  3. BLOCKED :阻塞状态,需要等待锁释放。

  4. WAITING:等待状态,表示该线程需要等待其他线程做出一些特定动作(通知或中断)。

  5. TIME_WAITING:超时等待状态,可以在指定的时间后自行返回而不是像 WAITING 那样一直等待。

  6. TERMINATED:终止状态,表示该线程已经运行完毕。

在这里插入图片描述

上下文切换

  • 什么是上下文?
    • 线程执行中自己的运行条件和状态(比如程序计数器、栈信息
  • 为什么会上下文切换?
    • 主动出让CPU
    • 时间片用完
    • 调用了阻塞类型的系统中断
    • 被终止或结束运行
  • 什么是上下文切换?
    • 线程切换,意味着要保存当前线程的上下文,留着线程下次占用CPU的时候恢复现场,并加载下一个将要占用CPU的线程上下文,所以要上下文切换
  • 切换的时候干啥?
    • 每次要保存信息恢复信息,占用CPU,所以不能频繁切换

sleep()和wait()

  • 二者异同
在这里插入图片描述
  • 为什么wait()不定义在Thread中?sleep()定义在Thread中?
    • wait() 是让获得对象锁的线程实现等待,会自动释放当前线程占有的对象锁。
      • 每个对象(Object)都拥有对象锁
      • 既然要释放当前线程占有的对象锁并让其进入WAITING状态,操作的对象自然是Object而不是当前线程Thread
    • sleep() 是让当前线程暂停执行,不涉及到对象类,也不需要获得对象锁
  • 可以直接调用Theard类的run方法吗?
    • 调用 start() 方法方可启动线程并使线程进入就绪状态,直接执行 run() 方法的话不会以多线程的方式执行

volatile

  • 如何保证变量的可见性?

    • 用 **volatile**关键字
    • 如果我们将变量声明为 volatile ,这就指示 JVM,这个变量是共享且不稳定的,每次使用它都到主存中进行读取。
    • volatile 关键字能保证数据的可见性,但不能保证数据的原子性。synchronized 关键字两者都能保证。
  • 如何禁止指令重排序?

    • 用 **volatile**关键字

    • 如果我们将变量声明为 volatile ,在对这个变量进行读写操作的时候,会通过插入特定的 内存屏障 的方式来禁止指令重排序。

    • volatile使用场景:双重校验锁实现对象单例(线程安全)

      • public class Singleton {
        
            private volatile static Singleton uniqueInstance;//volatile修饰!
            
            private Singleton() {}
            
            public  static Singleton getUniqueInstance() {
                if (uniqueInstance == null) {//没有实例化过才进入加锁代码
                    synchronized (Singleton.class) {//类对象加锁
                        if (uniqueInstance == null) {
                            /*这句话分三步进行:
                            1.为 uniqueInstance 分配内存空间
                            2.初始化 uniqueInstance
                            3.将 uniqueInstance 指向分配的内存地址
                            JVM指令重排,可能变成1->3->2,因此需要volatile*/
                            uniqueInstance = new Singleton();
                        }
                    }
                }
                return uniqueInstance;
            }
        }
        
  • volatile 可以保证原子性么?

    • 不能,只能保证可见性和有序性
    • 怎么改进?
      • synchronizedLock或者AtomicInteger

synchronized

synchronized主要解决的是多个线程之间访问资源的同步性,可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行

1. 使用场景

  • 1. 修饰实例方法(锁当前对象实例)

    • synchronized void method() {
          //业务代码
      }
      
  • 2. 修饰静态方法(锁当前类)

    • synchronized static void method() {
          //业务代码
      }
      
  • 3. 修饰代码块(锁指定对象/类)

    • synchronized(this) {
          //业务代码
      }
      
  • 注意:构造方法不能用synchronized修饰!(构造方法本身就线程安全)

2. 底层原理

底层依赖于JVM

  • synchronized 同步语句块

    • synchronized 同步语句块的实现使用的是 monitorentermonitorexit 指令,其中 monitorenter 指令指向同步代码块的开始位置,monitorexit 指令则指明同步代码块的结束位置。

    • 在执行**monitorenter**时,会尝试获取对象的锁,如果锁的计数器为 0 则表示锁可以被获取,获取后将锁计数器设为 1 也就是加 1。

    • 在这里插入图片描述
    • 对象锁的的拥有者线程才可以执行 monitorexit 指令来释放锁。在执行 monitorexit 指令后,将锁计数器设为 0,表明锁被释放,其他线程可以尝试获取锁。

    • 在这里插入图片描述
    • 如果获取对象锁失败,那当前线程就要阻塞等待,直到锁被另外一个线程释放为止。

  • synchronized 修饰方法

    • synchronized 修饰的方法并没有 monitorenter 指令和 monitorexit 指令,取得代之的确实是 ACC_SYNCHRONIZED 标识,该标识指明了该方法是一个同步方法。JVM 通过该 ACC_SYNCHRONIZED 访问标志来辨别一个方法是否声明为同步方法,从而执行相应的同步调用。

    • 如果是实例方法,JVM 会尝试获取实例对象的锁。如果是静态方法,JVM 会尝试获取当前 class 的锁。

  • 同步语句块用monitorenter 指令和 monitorexit 指令,修饰方法用**ACC_SYNCHRONIZED** 标识,不过两者的本质都是对对象监视器 monitor 的获取

3. 和volatile区别

synchronizedvolatile是互补的存在,区别有四点:

  • 性能volatile 关键字是线程同步的轻量级实现,性能比synchronized好
  • 使用volatile 只能用于变量,synchronized 可以修饰方法以及代码块
  • 并发特性volatile能保证数据的可见性,但不能保证数据的原子性。synchronized 关键字两者都能保证
  • 场景volatile主要用于解决变量在多个线程之间的可见性,而 synchronized 关键字解决的是多个线程之间访问资源的同步性

ReentrantLock

  • ReentrantLock 实现了 Lock 接口,是一个可重入独占式的锁
  • 底层:AQS(AbstractQueuedSynchronizer
    • ReentrantLock 里面有一个内部类 SyncSync 继承 AQS,添加锁和释放锁的大部分操作实际上都是在 Sync 中实现的
    • Sync 有公平锁 FairSync 和非公平锁 NonfairSync 两个子类
      • 公平锁:先等待的线程先获得锁
      • 非公平锁:随机线程获得锁,性能更好,但可能某些线程永远无法获得锁(ReentrantLock 默认)

在这里插入图片描述

和synchronized区别

  • 都是可重入锁
    • 可重入锁也叫递归锁,指的是线程可以再次获取自己的内部锁
    • JDK所有现成的Lock实现类,包括synchronized 关键字锁都是可重入的
  • 依赖对象不同
    • synchronized 依赖于 JVM
    • ReentrantLock 依赖于 API(需要lock()和unlock()方法配合try/finally语句块完成)
  • ReentrantLock功能更多
    • ReentrantLock增加了三点高级功能:
      • 等待可中断:正在等待的线程可以选择放弃等待,处理其他事情
        • 可中断锁:获取锁的过程可以被中断,进行其他逻辑处理【ReentrantLock】
        • 不可中断锁:一旦线程申请了锁,就只能等到拿到锁以后才能进行其他的逻辑处理【synchronized】
      • 可实现公平锁
        • ReentrantLock可以指定是公平锁还是非公平锁(默认非公平)
        • synchronized只能是非公平锁
      • 可实现选择性通知(锁可以绑定多个条件)
        • synchronized关键字与wait()notify()/notifyAll()方法相结合可以实现等待/通知机制
        • ReentrantLock类需要借助于Condition接口与newCondition()方法实现

AQS

核心思想:

如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。

如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,

这个机制 AQS 是用 CLH 队列锁 实现的,即将暂时获取不到锁的线程加入到队列中。

线程池

线程池就是管理一系列线程的资源池,有任务处理->线程池拿线程->处理完不销毁->线程等待下一个任务

1. 线程池作用

提供限制和管理资源的方式 && 维护一些基本统计信息

  • **降低资源消耗。**重复利用已创建的线程降低创建销毁的消耗。
  • **提高响应速度。**任务到达时,任务不需要等到线程创建就能立即执行。
  • **提高线程可管理性。**线程池统一分配、调优和监控线程。

2. 创建线程池方法

  1. ThreadPoolExecutor构造函数
  2. Executor 框架的工具类 Executors

3. 线程池饱和策略

线程达到最大数量,队列也被放满了任务,ThreadPoolExecutor.定义的策略:

  1. .AbortPolicy:抛出异常拒绝新任务的处理。
  2. .CallerRunsPolicy:调用自己的线程运行任务。
  3. .DiscardPolicy:不处理新任务,直接丢弃。
  4. .DiscardOldestPolicy:丢弃最老未处理的任务请求。

4. 常用阻塞队列

新任务到来->当前运行线程数==核心线程数?->√->新任务放队列

不同线程池用不同的阻塞队列

  1. LinkedBlockingQueue(无界队列):队列永远不会被放满
  2. SynchronousQueue(同步队列):没有容量,不存储元素。
  3. DelayedWorkQueue(延迟阻塞队列):内部采用“堆”

5. 线程池处理任务流程

在这里插入图片描述

6. 线程池大小

  • 太大->增加上下文切换成本

  • 太小->大量请求/任务堆积

  • CPU密集型任务(N+1):线程数设置为 N(CPU核心数)+1

  • I/O密集型任务(2N)

JVM

类加载机制

  • 类加载器:通过类的全限定性类名(带包路径,如java.lang.String)获取该类的二进制字节流
    • Bootstrap:加载java核心库(如$JAVA_HOME/jre/lib/rt.jar)
      • 好处:不需要太多的安全检查,提升性能
    • Extension:加载拓展库($JAVA_HOME/jre/lib/ext/*.jar)
    • AppClass:根据java的类路径加载类,一般的java应用的类($CLASSPATH)
    • 用户自定义:
  • 加载方式:双亲委派机制
    • 过程:
      • 收到类加载请求,不会自己加载,而是逐级向上委托,最终到达顶层的Bootstrap;
      • 如果父类加载器完成,则返回;否则,交给子类尝试。
    • 好处:
      • 避免类的重复加载:java类由于加载机制,形成了优先级的层次关系
      • 防止核心类被篡改:防止下层的同名类篡改核心API库
    • 打破这个机制
      • 意义:由于类加载器受到加载范围的限制,某些情况下父类加载器无法加载需要的类(不属于其加载范围,但根据机制只能其加载),所以需要子类加载器加载。
      • 方法:使用自定义加载器
      • 如何:
        • 1、找到ClassLoader类的loadClass()方法,拷贝
        • 2、写自定义加载器类,粘贴
        • 3、删去loadClass()中的双亲委派机制的部分
        • 4、判断类是否为系统类,是的话使用双亲委派机制,否则自己的方法加载。
      • 应用:
        • Tomcat:webappClassLoader加载自己目录下的class文件,目的;1、隔离每个webapp下的class和lib;2、使用单独的加载器以免被恶意破坏;3、热部署(修改文件不用重启自动重新装载)

垃圾回收(GC)

1. 引用类型

在这里插入图片描述

2. 垃圾收集

  • 垃圾:不再被使用的对象,死亡的对象

  • 哪些垃圾需要回收?

    • 引用计数法:每个对象添加一个引用计数器,当为0时,就表示死亡;

      • 问题:循环引用,不可回收造成内存泄露;空间占用
    • 可达性分析算法:以根对象集合(GC Roots)为起点,分析GC Roots连接的对象是否可达,解决了循环引用问题。

      在这里插入图片描述
      • GC Roots:就是对象!

        • 1、虚拟机栈中的栈帧中的局部变量所引用的对象;
        • 2、java本地方法栈中(java本地接口)引用的对象;
        • 3、方法区中静态变量引用的对象;(全局对象)
        • 4、方法区中常量引用的对象(全局对象)
      • 问题:多线程下更新了访问过的对象的引用

        • 误报:原被引用的对象不再被引用。影响较小,顶多减少GC次数。

        • 漏报:将已被访问过的对象设置为未被访问过。影响较大,可能会使引用对象被GC,导致jvm崩溃。

          • 解决方法:Stop-the-world,等所有线程到达安全点,再进行Stop-the-world。
            • Stop-the-world:用户运行至安全点(safe point)或者安全区域之后,就会挂起,进入暂停状态。
  • 什么时候回收?

    • Minor GC:young gc,发生在年轻代的gc
    • Major GC:olg gc,发生在老年代的gc
    • **Full GC:**回收整个堆的内存
      • 触发条件:
        • System.gc()
        • 通过Minor GC进入老年代的平均大小 > 老年代的可用内存
        • 老年代空间不足;

3. 垃圾回收算法(内存回收方法论)

在这里插入图片描述

4. 垃圾收集器(内存回收具体实现)

  1. Serial:

    • 单线程,所有线程stw,

    • 新生代标记-复制,老年代标记-整理

    • 缺点:需要停止所有工作线程,效率低

    • 场景:对应用的实时性要求不高的client级别(桌面应用)的默认方式,单核服务器

      在这里插入图片描述
  2. ParNew:

    • Serial的多线程版本,stw, 复制算法

    • 新生代标记-复制,老年代标记-整理

    • 实际线程默认和cpu数量相同

    • 优点:有效利用cpu

    • 缺点:和Serial一样

    • 场景:Sever模式下的新生代,和CMS配合

  3. Parallel Scavenge:

  • 新生代收集器、复制算法,多线程

  • 与ParNew不同点:追求和精确控制高吞吐量,而ParNew尽可能缩短用户线程的停顿时间;

    • 高吞吐:线程运行时间/线程运行时间 + 垃圾回收时间
    • 例子:PS就是100秒回收一次垃圾,持续10秒,吞吐量为90%;PN就是50秒回收一次垃圾,持续7秒,吞吐量为86%。
  • 场景:注重高效利用CPU

  1. Serial Old

    • Serial的老年代版本,标记整理算法

    • 场景:client、单核。与PS收集器搭配

  2. Parallel Old

    • Parallel Scavenge的老年代版本,多线程,标记整理算法

    • JDK7,8默认老年代收集器

  3. CMS

    • Concurrent Mark Sweep

    • 多线程、标记清除算法

    • 特点:获取最短回收停顿时间

在这里插入图片描述
  • 流程:
    • 1、初始标记:GC Roots直接关联的对象,需要Stw
    • 2、并发标记:与用户线程并发,不需要Stw,执行Gc Roots Tracing
    • 3、重新标记:修正并发标记期间,发生变动的一些标记,需要Stw
    • 4、并发清除:标记清除
  • 优点:并发收集,低停顿
  • 缺点:
    • 对CPU资源敏感
    • 标记清除产生空间碎片
    • 并发清除过程中会产生新的垃圾,只能等下一次
  1. G1(Garbage-First)

    • 标记整理 + 复制

      • 特点:

        • 并行与并发
        • 分代收集:自己采用不同的收集方式去处理不同代的垃圾,不需要和其他收集器合作
        • 空间整合:无空间碎片
        • 可预测的停顿:可预测时间的停顿模型
      • 原理:

        • 将java堆分为大小相同的独立区域Region,新生代和老年代区域混合;

          截屏2022-04-18 16.34.27
          • 并发标记:知道哪些块基本是垃圾,就会从这些块下手(所以叫G1);
          • 停顿预测模型:
            • 根据之前垃圾回收的数据统计,估计出用户指定停顿时间内的回收块个数;
          • “尽力”满足指定的目标停顿时间,基于目标选择回收的区块数量;
  • 步骤;

    • 1、Minor GC

      • 复制算法、并行、stw
      • 动态调整年轻区大小:根据历史数据,和用户指定的停顿时间目标
      • 2、老年代收集
      • 初始标记:stw,伴随young gc,对Gc Roots直接关联对象进行标记
      • 扫描根引用区:即survivor区的对象直接到老年代对象的引用。(因为进行了YGC,新生代中只有survivor区存在对象)
      • 并发标记:寻找整个堆的存活对象,并发执行,可以被YGC中断
        • 如果整个region都是垃圾,直接被回收
        • 标记的同时计算region活性比例
      • 重新标记:stw,完成最后的标记,使用了STAB算法
        • 由于用户线程同时进行,需要修正之前的标记
        • 采用了比CMS更快的初始快照法:SATB算法
      • 清理:stw,复制算法。计算各个region的存活对象和垃圾比例,排序,识别可以混合回收的区域 。
      • 并发清理:识别并清理全是垃圾的老年代region
      • 3、混合式收集:
      • 除了整个年轻代收集, 还有上个阶段标记出的老年代的垃圾最多的区块;
      • 持续回收所有被标记的分区
      • 恢复到年轻代收集,进行新的周期
      • 必要时的Full Gc:
        • G1的初衷就是避免Full GC

总结

  • 7种收集器关系

    如果两个收集器之间存在连线,就说明它们可以搭配使用

img

  • 收集器总结
收集器串/并行/并发新/老收集算法目标场景
Serial串行复制响应速度优先单CPU环境下的Client模式
Serial Old串行标记-整理响应速度优先单CPU环境下的Client模式、CMS的后备预案
ParNew并行复制响应速度优先多CPU环境时在Server模式下与CMS配合
Parallel Scavenge并行复制吞吐量优先在后台运算而不需要太多交互的任务
Parallel Old并行标记-整理吞吐量优先在后台运算而不需要太多交互的任务
CMS并发标记-清除响应速度优先集中在互联网站或B/S系统服务端上的Java应用
G1并发both标记-整理+复制算法响应速度优先面向服务端应用,将来替换CMS

设计模式

单例模式

  1. 懒汉式 - 线程不安全

    public class Singleton{
    	private static Singleton instance;
    	private Singleton(){}
    	public static Singleton getInstance(){
    		if(instance == null){
    			instance = new Singleton();
    		}
    		return instance;
    	}
    }
    
  2. 懒汉式 - 线程不安全

    public class Singleton{
    	private static Singleton instance;
    	private Singleton(){}
    	public static synchronized Singleton getInstance(){
    		if(instance == null){
    			instance = new Singleton();
    		}
    		return instance;
    	}
    }
    
  3. 双重检验锁

    public class Singleton{
    	private static Singleton instance;
    	private Singleton(){}
    	public static Singleton getInstance(){
    		if(instance == null){		// single check
    			synchornized(Singleton.class){
    				if(instance == null){		//double check
    					instance = new Singleton();
    				}
    			}
    		}
    		return instance;
    	}
    }
    
  4. 饿汉式 - static final field

    public class Singleton{
     	//类加载时就初始化
    	private static final Singleton instance = new Singleton();
    	private Singleton(){}
    	public static Singleton getInstance(){
    		return instance;
    	}
    }
    
  5. 静态内部类 - static nested class

    public class Singleton{
    	private static class SingletonHolder(){
    		private static final Singleton instance = new Singleton();
    	}
    	private Singleton(){}
    	public static final Singleton getInstance(){
    		return SingletonHolder.instance;
    	}
    }
    
  6. 枚举 - Enum

    public class Singleton{
    	private Singleton(){}
    	/**
    	*枚举类型是线程安全的,并且只会装载一次
    	*/
    	public enum SingletonEnum{
    		INSTANCE;
    		private final Singleton instance;
    		SingletonEnum(){
    			instance = new Singleton();
    		}
    		private Singleton getInstance(){
    			return instance;
    		}
    	}
    	
    	public static Singleton getInstance(){
    		return SingletonEnum.INSTANCE.getInstance();
    	}
    }
    
    

MySQL

存储引擎

  • MySQL 支持哪些存储引擎

    • MySQL 5.5.5 前:默认MyISAM;后:默认InnoDB
    • 只有 InnoDB 是事务性存储引擎,也就是说只有 InnoDB 支持事务。
  • 存储引擎架构

    • 插件式架构,支持多种存储引擎(不同数据库表可以设置不同搜索引擎)
    • 存储引擎是基于表的,而不是数据库
  • MyISAM 和 InnoDB 区别(7点)

    • MyISAM 性能还行,特性不错,但不支持事务和行级锁,最大的缺陷就是崩溃后无法安全恢复。

    在这里插入图片描述

索引

常见的索引结构有: B 树, B+树 和 Hash、红黑树。在 MySQL 中,无论是 Innodb 还是 MyIsam,都使用了 B+树作为索引结构。

1. 优缺点

优点

  • 使用索引可以大大加快 数据的检索速度(大大减少检索的数据量), 这也是创建索引的最主要的原因。
  • 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性

缺点

  • 创建索引和维护索引需要耗费许多时间。当对表中的数据进行增删改的时候,如果数据有索引,那么索引也需要动态的修改,会降低 SQL 执行效率。
  • 索引需要使用物理文件存储,也会耗费一定空间

2. 底层数据结构

B&B+树

  • 为啥不用哈希表做MySQL索引数据结构?

    • Hash 索引不支持顺序和范围查询,并且,每次 IO 只能取一个。
    • 试想,SELECT * FROM tb1 WHERE id < 500;,树直接遍历比 500 小的叶子节点就够了;哈希还要把1-499数据hash计算一遍来定位
  • B树和B+树区别?(3点)

    在这里插入图片描述
  • B+树比B树的优势

1.单一节点存储更多的元素,使得查询的IO次数更少;
  2.所有查询都要查找到叶子节点,查询性能稳定;
  3.所有叶子节点形成有序链表,便于范围查询。

3. 索引类型总结

在这里插入图片描述

事务

1. ACID

原子性Atomicity) : 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;

一致性Consistency): 执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;

隔离性Isolation): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;

持久性Durability): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

只有保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障。也就是说 A、I、D 是手段,C 是目的!

在这里插入图片描述

2. 并发事务问题

  • 脏读(Dirty read)

    某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的

  • 丢失修改(Lost to modify)

    在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。

  • 不可重复读(Unrepeatable read)

    在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。

  • 幻读(Phantom read)

    在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。

3. 并发事务控制方式

悲观控制模式

  • 共享锁(S 锁) :又称读锁,事务在读取记录的时候获取共享锁,允许多个事务同时获取(锁兼容)。
  • 排他锁(X 锁) :又称写锁/独占锁,事务在修改记录的时候获取排他锁,不允许多个事务同时获取。如果一个记录已经被加了排他锁,那其他事务不能再对这条记录加任何类型的锁(锁不兼容)。

MVCC

乐观控制模式

多版本并发控制(MVCC,Multiversion concurrency control) 在 MySQL 中实现所依赖的手段主要是: 隐藏字段、read view、undo log

  • undo log : undo log 用于记录某行数据的多个版本的数据。
  • read view 和 隐藏字段 : 用来判断当前版本数据的可见性。

4. 隔离级别

  1. 读取未提交(READ-UNCOMMITTED) : 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。

  2. 读取已提交(READ-COMMITTED) : 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。

  3. 可重复读(REPEATABLE-READ) : 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。

  4. 可串行化(SERIALIZABLE) : 最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。

在这里插入图片描述

锁机制

MVCC

RC和RR下 MVCC 的差异

在事务隔离级别 RCRR (InnoDB 存储引擎的默认事务隔离级别)下,InnoDB 存储引擎使用 MVCC(非锁定一致性读),但它们生成 Read View 的时机却不同

  • 在 RC 隔离级别下的 每次select 查询前都生成一个Read View (m_ids 列表)

  • 在 RR 隔离级别下只在事务开始后 第一次select 数据前生成一个Read View(m_ids 列表)

Redis

为什么用redis做mysql缓存?

1、高性能

  • MySQL从硬盘读取,慢。将用户缓存数据存在redis中,下次直接从缓存获取,相当于直接操作内存。
  • 为啥这么快?
    • 基于内存,访问速度是磁盘的上千倍
    • 基于reactor模式设计开发了一套高效事件处理模型,主要是单线程事件循环和io多路复用
    • 内置多种优化后的数据结构实现

2、 高并发

  • 单台设备的Redis的QPS(Query Per Second,每秒钟处理完请求的次数) 是 MySQL 的10倍
  • 直接访问 Redis 能够承受的请求远远大于直接访问 MySQL

数据结构

5 种基础数据结构 :String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合)。

3 种特殊数据结构 :HyperLogLogs(基数统计)、Bitmap (位存储)、Geospatial (地理位置)。

  • 常见数据结构

在这里插入图片描述
  • 底层数据结构

在这里插入图片描述

线程模型

  • 1. 单线程模式

在这里插入图片描述

  • 2. 单线程 v.s 多线程

在这里插入图片描述

缓存读写策略

1. 旁路缓存模式

  • 适用:读请求比较多的场景
  • 服务端同时维系 db 和 cache,以 db 的结果为准
  • 缓存读写步骤:
    • 写:
      • 先更新 db
      • 然后直接删除 cache
    • 读:
      • 从 cache 中读取数据,读取到就直接返回
      • cache 中读取不到的话,就从 db 中读取数据返回
      • 再把数据放到 cache 中

2. 读写穿透

  • 适用:读请求比较多的场景

3. 异步缓存写入

  • 适用:读请求比较多的场景

持久化

redis内存数据库,但会把缓存数据存到硬盘

->自带两种持久化技术:AOF日志&RDB快照

->redis默认开启RDB快照,重启redis,之前的缓存数据会被重新加载

AOF日志

在这里插入图片描述

RDB快照

  • AOF 文件的内容是操作命令;
  • RDB 文件的内容是二进制数据。

过期删除&内存淘汰策略

过期删除

计算机网络

HTTP与HTTPS

  • 区别
    • 传输安全:HTTP 是明文传输,存在安全风险的问题;HTTPS加密传输
    • 连接方式:HTTP是TCP;HTTPS是TCP基础上进行SSL/TLS
    • 端口号不同:HTTP 是 80;HTTPS是 443
    • 数字证书:HTTPS需要向CA申请数字证书
  • HTTPS解决了HTTP哪些问题?
    • 信息加密:交互信息无法被窃取,但你的号会因为「自身忘记」账号而没。
    • 校验机制:无法篡改通信内容,篡改了就不能正常显示,但百度「竞价排名」依然可以搜索垃圾广告。
    • 身份证书:证明淘宝是真的淘宝网,但你的钱还是会因为「剁手」而没。

HTTP/1.0 和 HTTP/1.1 和 HTTP/2.0

  • HTTP/1.0

    • 短连接
  • HTTP/1.1

    • 支持长连接
    • 同一个tcp连接中可以同时发送多个HTTP请求和响应
    • 增加host字段,http/1.0认为一台服务器只有一个ip地址,而现在存在多个虚拟主机共享一个ip
    • 新的状态码100(continue),表示客户端可以继续发送完整的请求(先发送一个不包含内容的请求试探)
  • HTTP/2.0

    • 兼容HTTP/1.1
    • 头部压缩
    • 二进制格式
    • 并发传输
    • 服务器主动推送资源

三次握手(建立TCP连接)

在这里插入图片描述

一次握手:客户端发送带有 SYN(SEQ=x) 标志的数据包 -> 服务端,然后客户端进入 SYN_SEND 状态,等待服务器的确认;

二次握手:服务端发送带有 SYN+ACK(SEQ=y,ACK=x+1) 标志的数据包 –> 客户端,然后服务端进入 SYN_RECV 状态

三次握手:客户端发送带有 ACK(ACK=y+1) 标志的数据包 –> 服务端,然后客户端和服务器端都进入ESTABLISHED 状态,完成TCP三次握手。

四次挥手(断开TCP连接)

在这里插入图片描述

第一次挥手 :客户端发送一个 FIN(SEQ=X) 标志的数据包->服务端,用来关闭客户端到服务器的数据传送。然后,客户端进入 FIN-WAIT-1 状态。

第二次挥手 :服务器收到这个 FIN(SEQ=X) 标志的数据包,它发送一个 ACK (SEQ=X+1)标志的数据包->客户端 。然后,此时服务端进入CLOSE-WAIT状态,客户端进入FIN-WAIT-2状态。

第三次挥手 :服务端关闭与客户端的连接并发送一个 FIN (SEQ=y)标志的数据包->客户端请求关闭连接,然后,服务端进入LAST-ACK状态。

第四次挥手 :客户端发送 ACK (SEQ=y+1)标志的数据包->服务端并且进入TIME-WAIT状态,服务端在收到 ACK (SEQ=y+1)标志的数据包后进入 CLOSE 状态。此时,如果客户端等待 2MSL 后依然没有收到回复,就证明服务端已正常关闭,随后,客户端也可以关闭连接了。

TCP v.s UDP

  • 七点不同:

在这里插入图片描述

  • UDP 一般用于即时通信,比如: 语音、 视频 、直播等等。

  • TCP 用于对传输准确性要求特别高的场景,比如文件传输、发送和接收邮件、远程登录等等。

DNS(域名IP映射)

应用层协议,基于UDP协议之上

在这里插入图片描述
  • 两种查询解析模式

    • 迭代

      主机->本地DNS->根服务器->TLD DNS->权威DNS->本地DNS->主机

      在这里插入图片描述
    • 递归

      在这里插入图片描述

操作系统

Spring

IoC

IoC(Inversion of Control:控制反转) 是一种设计思想,而不是一个具体的技术实现。

为什么叫控制反转?

  • 控制 :指的是对象创建(实例化、管理)的权力
  • 反转 :控制权交给外部环境(Spring 框架、IoC 容器)

在这里插入图片描述

AoP

AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

银行

  1. 为什么选择来银行?

    银行是一个有稳定发展前景的行业,而且在当今的经济环境下,银行的角色非常重要。选择银行是因为希望能够在一个稳定的行业中工作,同时为社会做出一些贡献。银行是一个注重团队合作和个人成长的行业。我希望能够在一个团结、相互协作的环境中工作,学习和发展自己的能力,不断提高自己的技能和经验,为银行和自己的未来发展做出贡献。

    我对银行的核心业务和金融知识有浓厚的兴趣。希望通过在银行的工作中,深入了解银行的业务和金融知识,并将其应用于日常工作中,以提高自己的专业技能和知识水平。

  2. 为什么选择邮储?

    选择来邮政储蓄工作是因为邮政储蓄是一家好公司,待遇也是不错的。因为中国邮政作为百年企业,有很强大的支撑基础,邮政储蓄银行作为其下属的子公司,在各项发展中是很有保障的,同时,邮政储蓄银行作为一个新独立的金融机构,相对于其他商业银行而言,其具有一个非常广泛、普及的网点优势。首先,邮政作为一个百年企业,它值得我信赖并将青春托付。其次,邮政提供的平台非常大,它能够给我足够的空间去磨练自己,展示才华。

面试题目

1. 拼多多 3.23

项目:不动产估值系统

  • 学到了什么?提到scrapy理论,问原理
在这里插入图片描述
  • 多源异构数据集?数据类型是什么?
  • 机器学习算法怎么实现的?用了哪些特征?
  • 评估指标是啥(准确率)?r2的含义是什么?
    • R2_score直观且不受量纲影响。其数值大小反映了回归贡献的相对程度,即在因变量Y的总变异中,回归关系所能解释的百分比,其值越高,说明模型的解释性越好。
  • 还用过其他评估指标吗?还知道其他评估指标吗?
    • 平均绝对误差、均方误差、均方根差、均方根百分误差、决定系数R2
    • 前四种问题:量纲不同时,难以衡量模型效果好坏,并且可读性较差
在这里插入图片描述
  • 训练集和测试集怎么划分的?为什么这么划分?(这么划分结果最好
  • 为什么其他划分方式结果不好?有分析吗?
  • 训练集测试集划分比例有什么影响?过拟合是什么意思?
  • 个人能力比较突出的是什么?
  • 华融实习都是自己做的吗?
  • 遇到过什么问题?怎么解决?印象比较深花时间比较多的(提到了版本不一致报错)
  • java遇到版本不一样问题怎么办?a库和b库都用到了c库

java

  1. 类加载机制

  2. 垃圾回收机制

数据库

  1. redis和mysql有什么不同?为啥用redis做缓存?

  2. redis数据结构?

算法

上海[180.65.28.0, 186.75.28.0]

重庆[101.0.0.0,101,255,255,255]

…一共十万行

然后给ip地址(字符串),返回城市名称,没有对应城市返回""

反问:什么部门?做什么?跨境电商 海外业务 推荐搜索

2. 美团-履约 3.24

项目

  1. 爬虫策略 数据量

  2. 用过大数据挖掘吗?spark这些?

MySQL

  1. 介绍索引

  2. B树和B+树区别

  3. 还有别的索引吗?都用的B+树吗?

  4. 聚簇索引 非聚簇索引

  5. 主键索引 非主键索引

java

  1. 垃圾回收算法

  2. java的锁synchronize,lock

  3. 介绍线程池

  4. 强引用 弱引用

算法:2. 两数相加 - 力扣

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode dummyHead=new ListNode(-1);
        ListNode p=dummyHead;
        int add=0;
        while(l1!=null||l2!=null||add>0){
            int a=l1==null?0:l1.val;
            int b=l2==null?0:l2.val;
            int ans=a+b+add;
            p.next=new ListNode(ans%10);
            add=ans/10;
            p=p.next;
            if(l1!=null)
                l1=l1.next;
            if(l2!=null)
                l2=l2.next;
        }
        return dummyHead.next;
    }
}

3. 联想 3.27

图书项目

  1. spring boot和spring的区别?
    • 最大的区别在于Spring Boot的自动装配原理
    • 比如:
      • 创建Web程序时:Spring-导入几个Maven依赖,Spring Boot-只需要一个Maven依赖
      • 开启功能:Spring-XML文件配置,Spring Boot-不用XML配置,只需要写一个配置类
    • Spring Boot是一个微服务框架,延续了Spring框架的核心思想IOC和AOP,简化了应用的开发和部署,是Spring的完善和扩展
  2. mysql中有几种表?分别存的数据项是什么?
    • user,book,category(图书类别),admin_role(用户角色),admin_permission(用户权限),admin_role_menu(用户角色菜单),admin_role_permission(用户角色权限)
    • book表:id,cover,title,author,date,press,abs,cid(类别做外键)
  3. 项目中redis用什么客户端部署?
    • Java 访问 Redis 主要是通过 JedisLettuce 两种由不同团队开发的客户端(提供访问、操作所需的 API),Jedis 比较原生,Lettuce 提供的能力更加全面
    • 本项目用Spring Data Redis,Spring Data Redis是在 Lettuce 的基础上做了一些封装,与 Spring 生态更加贴合,使用起来也更简便。
  4. redis用的哪种数据结构存储图书?
    • RedisTemplate是 Spring Data Redis 提供的一个完成 Redis 操作、异常转换和序列化的类
    • String类型key,Set keys,List< Book >存图书列表
  5. List存取的api了解吗?
    • append,get
  6. redis缓存是所有图书都存进去吗?
  7. 数据库组建怎么实现的?
  8. mysql中事务是怎么添加的?
    • 步骤1:开启事务
      set autocommit=0;
      start transaction;可选的
    • 步骤2:编写事务中的sql语句(select、insert、update、delete)
      语句1;
      语句2;
    • 步骤3:结束事务
      commit;提交事务
      rollback;回滚事务
  9. 一个mapper两个update怎么保证事务不冲突?(答锁,纠正我锁是保证数据一致性的
    • MVCC
      • undo log
      • 隐藏字段
      • ReadView

抵押品项目

怎么构建的数据集?

java

  1. static和final什么时候用?为什么要用?

    • static
      • 加载:类加载时初始化(加载)完成
      • 可修饰:内部类、方法、成员变量、代码块
      • 不可修饰:外部类、局部变量
      • 作用:方便调用没有创建对象的方法/变量
    • final
      • 加载:final可以在编译(类加载)时初始化,也可以在运行时初始化,初始化后不能被改变
      • 可修饰:成员变量、方法、类以及本地变量
      • 一旦你将引用声明作 final,你将不能改变这个引用了,保证数据安全性
    • static final
      • 可修饰:成员变量、方法、内部类
      • 被static final修饰意义如下
        • 成员变量:属于类的变量且只能赋值一次。
        • 方法:属于类的方法且不可以被重写。
        • 内部类:属于外部类,且不能被继承。
  2. Object常用hashCode()和equals(),什么时候需要重写?

    • 1)当我们需要重新定义两个对象是否相等的条件时,需要进行重写。比如通常情况下,我们认为两个不同对象的某些属性值相同时就认为这两个对象是相同的。

      例如:我们在HashMap中添加元素时,我们认为当key相同时,两个元素就相同,但是默认的Object中的equals(),只是单纯的比较两个元素 的内存地址是否相同,不能满足我们的要求,所以需要重写。

    • 2)当我们自定义一个类时,想要把它的实例保存在集合时,就需要重写equals()和hashCode()方法

  3. ArrayList的底层数据结构

    • Object[]数组
  4. HashMap的底层数据结构?

    • jdk1.8之前:数组+链表(链表散列)
    • jdk1.8之后:链表长度>阈值(默认8),将其转化为红黑树,减少搜索时间
  5. HashMap数组中怎么存的?

    • 存的hash值,链表中存键值对
    img
  6. 哈希冲突是什么?

  7. synchronize怎么用?啥时候用?

    • 修饰实例方法:进入同步代码前要获得 当前对象实例的锁
    • 修饰静态方法:进入同步代码前要获得 当前 class 的锁
    • 修饰代码块
      • synchronized(object) 表示进入同步代码库前要获得 给定对象的锁
      • synchronized(类.class) 表示进入同步代码前要获得 给定 Class 的锁

算法(口述)

  • 两个数组找交集,令时间复杂度最小(答用set 时间复杂度是多少?
    • 排序 + 双指针:初始时,两个指针分别指向两个数组的头部。每次比较两个指针指向的两个数组中的数字,如果两个数字不相等,则将指向较小数字的指针右移一位,如果两个数字相等,且该数字不等于 pre ,将该数字添加到答案并更新 pre 变量,同时将两个指针都右移一位。当至少有一个指针超出数组范围时,遍历结束。

4. 蚂蚁-数金 3.28

押品项目

  1. 从哪些维度对数据进行挖掘?得到什么样的结果?哪些对算法模型有决定性作用
  2. 系统开发后端是不是增删改查这些?用的什么数据库

java

  1. 保证线程安全的办法?(答锁,问我还有其他吗,没答出来

    • 互斥同步:synchronized是最常用的
    • 非阻塞同步
    • 无同步方案
  2. 说说对锁的了解(答乐观锁和悲观锁

    • 乐观锁实现:版本号orCAS

    • 悲观锁实现:synchronizedLock等独占锁就是悲观锁

  3. 悲观锁用什么实现?(答synchronized和ReentrantLock

  4. synchronized和其他独占锁底层是怎么实现的?

    • synchronized底层:
  5. java为什么会存在线程安全的问题?底层原因是什么?(答并发,跟我说是表象,问更深层是什么原因

  6. java本身jvm或者内存什么样的设计特点决定它存在这样的问题?(答线程共享堆和方法区资源,同时修改会发生安全问题,他还问更深层的是什么

    • 线程共享:方法区,堆(有线程安全问题)

    • 线程独享:栈、本地方法栈、计数器(不存在线程安全问题)

  7. 了解java内存模型吗?新增一个线程,线程里的变量存在于什么地方?(答栈

  8. 这个栈空间是共享的还是独享的?(答共享的,纠正我有一部分共享一部分独享,共享function,独享变量

    变量独享,做复制,拷贝到工作内存,更改完需要回刷,产生XXx操作,是问题的根本原因

  9. ConcurrentHashMap的源码了解(答了一下初始化源码

mysql

  1. 索引结构(答b+树
  2. b+树特点
  3. b+树每一层都是链表(我说只有叶子是,纠正我mysql不是标准b+树,是变种
  4. 查询语句建索引,abc三个字段,有一条语句“a=?,c=?”,“?”是占位符,这个语句能不能用到abc复合索引?(答能,问原因不会

redis

  1. 读数写数单线程,那为什么性能那么好?(三点

Spring boot

  1. 动态加载和动态配置化为开发带来了哪些便利?

  2. 你在开发中用到了什么动态加载和动态配置化?

    (答spring用xml,sb用配置类,纠正:Spring也可以用注解不用xml配置,动态加载和用不用配置没啥关系

算法

  1. 线程安全的单例模式
  2. 快排
  3. 有序数组找第一个大于x的元素下标

其他

​ 工作和学习中做的最有挑战或者最有成就感的一件事是什么?

5. 美团-酒旅 3.30

押品项目

  1. 难点?
  2. 对数据挖掘的结果是什么?什么数据对结果影响比较大?
  3. 再来一个数据集?怎么把它变成同构的?
  4. 算法还有提升空间吗?有多少提升空间?怎么提升?试过什么方法?提升了多少?
  5. 没用过的那些算法准确率有多少?
  6. 系统都有什么功能?
  7. 实习做的算法?为啥找开发?

图书项目

  1. 怎么用的maven?
  2. 为什么采用shiro框架?还知道什么安全框架?(答Spring Security
  3. Spring Security和shiro有什么区别?为什么没用Spring Security?
  4. 项目里redis用的哪种数据结构?键是什么?(答List,键是图书id,他质疑我键不对

Java

  1. java异常机制的了解

    在 Java 中,所有的异常都有一个共同的祖先 java.lang 包中的 Throwable 类。

image-20230403224929321
  1. 设计一个java线程池

  2. Integer a=128; Integer b=128; System.out.println(a==b);
    

    结果是啥?(应该是true,我答的false,他问我不是有常量池吗

  3. public static void main(String[] args) {
        Integer numValue=new Integer(1);
        int a=1;
        int b=2;
        Integer nullValue=null;
        if(a==1)
            b=nullValue;
        else if(b==2)
            a=nullValue;
        System.out.println(numValue);
        System.out.println(nullValue);
        System.out.println(a);
        System.out.println(b);
    }
    

    结果是啥?(代码大概是这样,结果是编译错误T_T,int型(b)不能为null,Integer可以为null

  4. 类加载机制?

  5. 知道哪些类加载器(ClassLoader)?

    • BootstrapClassLoader(启动类加载器) :最顶层的加载类,主要用来加载 JDK 内部的核心类库

    • ExtensionClassLoader(扩展类加载器) :主要负责加载 %JRE_HOME%/lib/ext 目录下的 jar 包和类以及被 java.ext.dirs 系统变量所指定的路径下的所有类。

    • AppClassLoader(应用程序类加载器) :面向我们用户的加载器,负责加载当前应用 classpath 下的所有 jar 包和类。

  6. 垃圾回收机制的了解?(答回收算法,纠正我分代收集不算一种算法

  7. 哪几种收集器用的标记-整理?哪几种用的复制?

操作系统

  1. 构造一个死锁

    public class DeadLock {
    
    
        private class Running1 implements Runnable {
            /*
             * This method request two locks, first String and then Integer
             */
            @Override
            public void run() {
                while (true) {
                    synchronized (String.class) {
                        System.out.println("Thread1 Aquired lock on String.class object");
        
                        synchronized (Integer.class) {
                            System.out.println("Thread1 Aquired lock on Integer.class object");
                        }
                    }               
                }
            }
        
        }
        
        private class Running2 implements Runnable {
            /*
             * This method also requests same two lock but in exactly
             * Opposite order i.e. first Integer and then String
             * This creates potential deadlock, if one thread holds String lock
             * and other holds Integer lock and they wait for each other, forever
             */
            @Override
            public void run() {
                while (true) {
                    synchronized (Integer.class) {
                        System.out.println("Thread2 Aquired lock on Integer.class object");
        
                        synchronized (String.class) {
                            System.out.println("Thread2 Aquired lock on String.class object");
                        }
                    }               
                }
            }       
        }
        
        public static void main(String[] args) {
            DeadLock deadLock = new DeadLock();
            Running1 r1 = deadLock.new Running1();
            Running2 r2 = deadLock.new Running2();
        
            Thread thread1 = new Thread(r1);
            Thread thread2 = new Thread(r2);
        
            thread1.start();
            thread2.start();
        }
    
    }
    

    在上面这个例子中,我们有两个线程,以相反的顺序去获取两个锁,最后陷入了Thread1持有String锁,等待Integer锁,Thread2持有Integer锁,等待String锁的无限等待,即死锁情景

MySQL

  1. InnoDB和MyISAM的区别(7点

  2. 为什么InnoDB的性能更强大?

    • MyISAM 因为读写不能并发,它的处理能力跟核数没关系。
    • 在读写混合模式或者只读模式下,随着 CPU 核数的增加,InnoDB 的读写能力呈线性增长。
  3. 为什么要主键自增?

    • 1.数据记录本身被存于主索引的叶子节点上
    • 2.mysql会根据其主键将其插入适当的节点和位置
    • 3.表使用自增主键,在每次插入新的记录时,记录会顺序添加到当前索引节点的后续位置

redis

  1. 说说对redis的了解(答高性能和高并发

  2. redis为什么用单线程?

    • 单线程编程容易并且更容易维护;
    • Redis 的性能瓶颈不在 CPU ,主要在内存和网络;
    • 多线程就会存在死锁、线程上下文切换等问题,甚至会影响性能。
  3. 哪几种底层数据结构?每种数据结构的使用场景?

    • String

      • 存储常规数据

      • 计数

      • 分布式锁

    • List

      • 信息流展示

      • 消息队列

    • Set

      • 存放的数据不能重复(点赞…

      • 获取多个数据源交集、并集和差集(共同好友、音乐推荐…

      • 随机获取数据源中的元素(抽奖系统…

    • Hash

      • 对象数据存储(用户信息、文章信息…
    • Zset

      • 随机获取数据源中的元素根据某个权重进行排序(朋友圈的微信步数排行榜…

      • 存储的数据有优先级或者重要程度(优先级任务队列

  4. io多路复用是怎么复用的?

    • 目的:让单线程(进程)的服务端应用同时处理多个客户端的事件

    • 含义:**“多路”指的是多个网络连接客户端,“复用”**指的是复用同一个线程(单进程)。

      I/O 多路复用其实是使用一个线程来检查多个Socket的就绪状态,在单个线程中通过记录跟踪每一个socket(I/O流)的状态来管理处理多个I/O流。

    在这里插入图片描述

算法

  1. sql:student表里找成绩第二的

  2. 有序数组,遍历一次找出所有a+b=m的数字(要运行)

    追问:数组是空怎么办?数组是[2,2,5,5]怎么办?

反问:对校招生的建议(告诉我美团注重基础

6. 快手-海外业务 4.20

java

  1. 基本数据类型,每种对应多少字节?

    image-20230420212018452
  2. Integer a=127; Integer b=127; Integer c=128; Integer d=128; System.out.println(a==b);//返回true;
    System.out.println(c==d);//返回false;
    

    直接使用Integer包装类赋值,范围在[-128,127]之间不会生成新的对象,直接把缓存中的对象拿来用,超过了范围就相当于在堆中new一个对象,然后双等于就是比较两者的内存地址是否一样

  3. 说一下hashmap,为什么容量是2的幂次方,怎么定位的?

    指定初始容量,容量会变成大于这个值的2的次幂的最小值;

    • 原因:源码:(n - 1) & hash
    • 好处:
      • &运算比%快
      • 保证索引在capacity中,不会越界
      • 当n为2次幂时,(n - 1) & hash = hash % n
  4. 静态方法先执行吗?父类和子类谁先执行?(静、父类

  5. 说一下线程池

  6. 说一下JVM的内存管理(不会…

mysql

  1. 说一下四种隔离级别
  2. mysql默认的隔离级别?
  3. 读取已提交不能阻止脏读,那么mysql怎么解决的呢?用的什么锁?
  4. InnoDB默认隔离级别?

算法

  1. 手写单例模式

  2. 未排序数组中找第k个最大数,都有什么算法?实现堆和快排,时间复杂度是多少?

7. 邮储-北京 4.25

hr:

项目中一般扮演什么样的角色?
项目:

  1. 校企联合还是实习项目?
  2. 怎么进行评估的 balabala(感觉面试官不太懂机器学习

八股

  1. 线程之间如何通信?

    线程通信就是当多个线程共同操作共享的资源时,互相告知自己的状态以避免资源争夺。

    • 共享内存:线程之间共享程序的公共状态,线程之间通过读-写内存中的公共状态来隐式通信
      • volatile共享内存
    • 消息传递:线程之间没有公共的状态,线程之间必须通过明确的发送信息来显示的进行通信
      • wait/notify等待通知方式
        join方式
    • 管道流
      • 管道输入/输出流的形式
  2. 什么是死锁?怎么解除死锁?

    • 死锁:多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都无法向前推进
    • 在这里插入图片描述
  3. https如何建立安全通道?

    HTTP明文传输->三个风险:窃听、篡改、冒充

    • 客户端发起HTTPS请求
    • 服务端将数字证书和公钥发送给客户端
    • 客户端验证数字证书是否合法,然后使用公钥将自己生产的随机密钥进行加密
    • 客户端将加密后的密钥发送给服务端
    • 服务端使用自己的私钥将加密后的密钥进行解密,得到对称加密算法的密钥。接下来的数据可以通过这个密钥进行加密后传。

8. 阿里-ICBU 4.26

30min电话面

项目

  1. 做图书阅读管理系统的目的?
  2. 为什么要做抵押品估值系统?
  3. 估值模型是怎么设计的?
  4. 系统怎么存储?几张表?
  5. 模型上线之后怎么评优?怎么迭代?

Springboot

  1. 在开发过程中主要解决什么问题?(答简化开发过程
  2. 以前哪个环节比较耗时?用Springboot简化了
  3. 常用的注解?
  4. 加事务的注解?(@Transactional
  5. 事务注解的参数?
    • propagation(事务的传播行为)、isolation(事务的隔离级别)、timeout(超时时间)、readONLY(是否只读)、rollbackFor(回滚)、noRollbackfor(不回滚)
  6. AOP和IOC的含义?
  7. 了解过AOP和IOC的实现吗?如果自己做一套IOC怎么做?
  8. 实例化交给框架做带来的好处是什么?

MyBatis

  1. MyBatis是做什么的?(操作数据库
  2. MyBatis操作方式有什么优势?(提了JPA,说了一下二者区别
  3. MyBatis比JDBC的优势?(减少代码量、更灵活…
  4. 说一下对ORM的了解(为了解决面向对象与关系数据库存在的互不匹配的现象的技术

Java

  1. 怎么生成一个线程?
  2. 线程池有什么作用?
  3. 怎么结束一个线程池?(shutdown
  4. 多线程里原子性、可见性、有序性是什么概念?
  5. 为什么会出现可见性的概念?

9. 字节-4.28

) & hash**

  • 好处:
    • &运算比%快
    • 保证索引在capacity中,不会越界
    • 当n为2次幂时,(n - 1) & hash = hash % n
  1. 静态方法先执行吗?父类和子类谁先执行?(静、父类
  2. 说一下线程池
  3. 说一下JVM的内存管理(不会…

mysql

  1. 说一下四种隔离级别
  2. mysql默认的隔离级别?
  3. 读取已提交不能阻止脏读,那么mysql怎么解决的呢?用的什么锁?
  4. InnoDB默认隔离级别?

算法

  1. 手写单例模式

  2. 未排序数组中找第k个最大数,都有什么算法?实现堆和快排,时间复杂度是多少?

7. 邮储-北京 4.25

hr:

项目中一般扮演什么样的角色?
项目:

  1. 校企联合还是实习项目?
  2. 怎么进行评估的 balabala(感觉面试官不太懂机器学习

八股

  1. 线程之间如何通信?

    线程通信就是当多个线程共同操作共享的资源时,互相告知自己的状态以避免资源争夺。

    • 共享内存:线程之间共享程序的公共状态,线程之间通过读-写内存中的公共状态来隐式通信
      • volatile共享内存
    • 消息传递:线程之间没有公共的状态,线程之间必须通过明确的发送信息来显示的进行通信
      • wait/notify等待通知方式
        join方式
    • 管道流
      • 管道输入/输出流的形式
  2. 什么是死锁?怎么解除死锁?

    • 死锁:多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都无法向前推进
    • 在这里插入图片描述
  3. https如何建立安全通道?

    HTTP明文传输->三个风险:窃听、篡改、冒充

    • 客户端发起HTTPS请求
    • 服务端将数字证书和公钥发送给客户端
    • 客户端验证数字证书是否合法,然后使用公钥将自己生产的随机密钥进行加密
    • 客户端将加密后的密钥发送给服务端
    • 服务端使用自己的私钥将加密后的密钥进行解密,得到对称加密算法的密钥。接下来的数据可以通过这个密钥进行加密后传。

8. 阿里-ICBU 4.26

30min电话面

项目

  1. 做图书阅读管理系统的目的?
  2. 为什么要做抵押品估值系统?
  3. 估值模型是怎么设计的?
  4. 系统怎么存储?几张表?
  5. 模型上线之后怎么评优?怎么迭代?

Springboot

  1. 在开发过程中主要解决什么问题?(答简化开发过程
  2. 以前哪个环节比较耗时?用Springboot简化了
  3. 常用的注解?
  4. 加事务的注解?(@Transactional
  5. 事务注解的参数?
    • propagation(事务的传播行为)、isolation(事务的隔离级别)、timeout(超时时间)、readONLY(是否只读)、rollbackFor(回滚)、noRollbackfor(不回滚)
  6. AOP和IOC的含义?
  7. 了解过AOP和IOC的实现吗?如果自己做一套IOC怎么做?
  8. 实例化交给框架做带来的好处是什么?

MyBatis

  1. MyBatis是做什么的?(操作数据库
  2. MyBatis操作方式有什么优势?(提了JPA,说了一下二者区别
  3. MyBatis比JDBC的优势?(减少代码量、更灵活…
  4. 说一下对ORM的了解(为了解决面向对象与关系数据库存在的互不匹配的现象的技术

Java

  1. 怎么生成一个线程?
  2. 线程池有什么作用?
  3. 怎么结束一个线程池?(shutdown
  4. 多线程里原子性、可见性、有序性是什么概念?
  5. 为什么会出现可见性的概念?

9. 字节-4.28


http://www.kler.cn/a/17475.html

相关文章:

  • 【算法一周目】双指针(2)
  • 文件输入输出——NOI
  • MySql结合element-plus pagination的分页查询
  • 利用滑动窗口解题
  • MySQL Workbench导入数据比mysql命令行慢
  • Springboot集成syslog+logstash收集日志到ES
  • 一个go http和grpc客户端库
  • Zigbee 无线串口通信模块( DL-22 )
  • 【Python入门篇】——Python基础语法(标识符与运算符)
  • 文献集锦 | 非因生物空间多组学技术在头颈部肿瘤中的研究策略
  • 7.3 有源滤波电路(1)
  • Springcloud--docker快速入门
  • k8s DCGM GPU采集指标项说明
  • 操作系统之死锁处理策略
  • 体验 nanoGPT
  • PWLCM分段线性混沌映射
  • 日语学习(一)
  • flink-on-yarn两种提交模式及其区别
  • 【Linux问题合集001】Linux中如何将用户添加到sudo组中的步骤
  • 武忠祥老师每日一题||不定积分基础训练(六)
  • Lattics ——一款简单易用、好看强大的知识管理工具
  • 【Spring Security第一篇】初始Spring Security、表单认证、认证与授权
  • Docker安全最佳实践
  • 算法的时间复杂度和空间复杂度(友友们专属限定版)
  • linux常用操作
  • Java ---比较器