2021届Java开发求职-------面试实战之美团数据平台

一.前言

虽然从大三开始就实习好久了,但是现在可能也面临找工作(假如现在没法转正的话),所以找点面经巩固一下知识,嘿嘿,算法也要看,每天一道leetcode先吧


二.具体内容

这是一份美团的 链接:https://www.nowcoder.com/discuss/352030

一面
JVM:

JVM的结构:

这个要分公有,私有:(针对线程而言

  • 公有部分:堆区,方法区
  • 私有部分:程序计数器,虚拟机栈,本地方法栈
  • 详细的文章:JVM内存结构

新生代和老年代的垃圾回收算法:

这个首先得明确新生代和老年代是什么,也就是JVM堆结构这块,

在这里插入图片描述

这是Java堆的内存结构,可以看出来,整个堆区分为两个大块----年轻代和老年代。年轻代内又分为Eden区,From Survivor 0 区和To Survivor 1区,其默认比例为8比1。为什么要这么划分呢? 年轻代中的对象基本都是朝生夕死的(80%以上),也正因如此,在年轻代的垃圾回收算法使用的是复制算法,复制算法的基本思想就是将内存分为两块,每次只用其中一块,当这一块内存用完,就将还活着的对象复制到另外一块上面。复制算法不会产生内存碎片。

总结:对于存活对象少的新生代区域,比较适合采用复制算法。这样只需要复制少量对象,便可完成垃圾回收,并且还不会有内存碎片。而对于老年代这种存活对象多的区域,比较适合采用标记压缩算法或标记清除算法,这样不需要移动太多的内存对象。

虚拟机栈和本地方法栈的区别:

虚拟机栈:这个栈与线程同时创建,用来存储栈帧,即存储局部变量与一些过程结果的地方。栈帧存储的数据包括:局部变量表、操作数栈。

本地方法栈:本地方法栈与虚拟机栈基本类似,区别在于虚拟机栈为虚拟机执行的java方法服务,而本地方法栈则是为Native方法服务。

类信息会加载到JVM哪个区域

方法区

HashMap 和 ConcurrentHashMap 的区别

一般而言concurrentHashMap是线程安全的,具体实现:在1.7采取的segment分段锁,有点类似于16个线程安全的hashtable组合成了一个concurrenthashmap,不同分段操作不需要上锁,同一个分段才需要上锁,读不上锁,写上锁。锁的粒度更加精细。而1.8采取的AQS和CAS来实现。

final 的作用,加在变量、方法、类的区别
  1. 修饰变量,为常量,值不可变
  2. 修饰对象,值可变,引用不变
  3. 修饰方法,方法不可重写
  4. 修饰类,无子类,不可以被继承
新建一个 string 会创建几个对象

(1)字面量赋值方式 eg:String str = “Hello”;

该种直接赋值的方法,JVM会去字符串常量池(String对象不可变)中寻找是否有equals(“Hello”)的String对象,如果有,就把该对象在字符串常量池中"Hello"的引用复制给字符串变量str,如若没有,就在堆中新建一个对象,同时把引用驻留在字符串常量池中,再把引用赋给字符串变量str。

用该方法创建字符串时,无论创建多少次,只要字符串的值(内容)相同,那么它们所指向的都是堆中的同一个对象。

该方法直接赋值给变量的字符串存放在常量池里

(2)new关键字创建新对象 eg:String str = new String(“Hello”);

利用new来创建字符串时,无论字符串常量池中是否有与当前值相同的对象引用,都会在堆中新开辟一块内存,创建一个新的对象。如果算上栈的引用str,如果字符串常量池有"Hello",那么两个,否则三个。

哪些类是线程安全的

这题感觉比较泛,随便答一下

线程池的参数;为什么需要超出最大容量的策略

本人的博文:线程池七大参数

ThreadLocal了解吗

线程局部变量是局限于线程内的变量,属于线程自身所有,不在多个线程间共享。java提供ThreadLocal类来支持线程局部变量,是一个实现线程安全的方式。


Spring

AOP的实现原理 :动态代理

CGLIB动态代理与JDK动态区别

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

Spring中:

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP

2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP

3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

JDK动态代理只能对实现了接口的类生成代理,而不能针对类 。 CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 。 因为是继承,所以该类或方法最好不要声明成final ,final可以阻止继承和多态。

@Autowired和@Resource的区别

@Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。@Resource注解和@Autowired一样,也可以标注在字段或属性的setter方法上,但它默认按名称装配。名称可以通过@Resource的name属性指定,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。

什么情况下会用@Resource

当需要在某个类中定义一个属性,并且该属性是一个已存在的bean,要为该属性赋值或注入时在该属性上一行使用@Resource(name=“xxx”),相当于为该属性注入一个名称为xxx的bean。

MySQL

B+树的优势

1.单次请求涉及的磁盘IO次数少(出度d大,且非叶子节点不包含表数据,树的高度小);
2.查询效率稳定(任何关键字的查询必须走从根结点到叶子结点,查询路径长度相同);
3.遍历效率高(从符合条件的某个叶子节点开始遍历即可);

悲观锁和乐观锁了解吗

乐观锁和悲观锁是两种思想,用于解决并发场景下的数据竞争问题。

  • 乐观锁:乐观锁在操作数据时非常乐观,认为别人不会同时修改数据。因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据:如果别人修改了数据则放弃操作,否则执行操作。
  • 悲观锁:悲观锁在操作数据时比较悲观,认为别人会同时修改数据。因此操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据。
数据库如何实现乐观锁

乐观锁的实现方式主要有两种:CAS机制和版本号机制,具体解释:

工厂模式怎么理解
单例模式有哪几种实现方式

参考本人博客,懒汉式,饿汉式,双检锁等

算法

反转链表:一道比较常规的题目,可以用递归来做也可以迭代:

二面

JAVA基础
HashMap 和 ConcurrentHashMap 的区别:

之前有了

hash 冲撞怎么办?如何 rehash

开放地址法,rehash法,拉链法。

HashMap 的遍历方式

看这个把:https://www.cnblogs.com/Bkxk/p/11063720.html

为什么 HashMap 是线程不安全的

(1)在put的时候,因为该方法不是同步的,假如有两个线程A,B它们的put的key的hash值相同,不论是从头插入还是从尾插入,假如A获取了插入位置为x,但是还未插入,此时B也计算出待插入位置为x,则不论AB插入的先后顺序肯定有一个会丢失

(2)在扩容的时候,jdk1.8之前是采用头插法,当两个线程同时检测到hashmap需要扩容,在进行同时扩容的时候有可能会造成链表的循环,主要原因就是,采用头插法,新链表与旧链表的顺序是反的,在1.8后采用尾插法就不会出现这种问题,同时1.8的链表长度如果大于8就会转变成红黑树。

volatile 和 synchronized 的区别

1、volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
2、volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
3、volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
4、volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
5、volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化

总结

其实问的比较基础,也挺全的,感觉hashmap还是挺重要

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值