美团后端Java实习一面面经

说一下AOP?

面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的技术。可以减少程序中相同代码的编写,简化开发,使得接口更加专注于业务

相关概念

  • Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。

 

  • Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。

 

  • Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。

 

  • Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。

如何实现

1. AspectJ

AspectJ主要作用于编译时增强, 也称之为静态代理, 我们在写完一段独立的业务方法saveData()时, 可以使用aspectJ将切面逻辑织入到saveData()中. 比如日志记录.

在使用aspectJ编译代码之后, 我们的class文件中会多出一段代码, 这段代码是aspectJ在编译时增加的aop代码. AspectJ的这种做法可以被称为静态代理

Aspect在编译期, 为被代理方法织入我们在aspect中定义好的切面逻辑, 以添加字节码的方式(强行添加代码)

2. JDK动态代理

jdk动态代理使用jdk自带的反射机制来完成aop的动态代理, 使用jdk自带的动态代理有如下要求:

1.被代理类(我们的业务类)需要实现统一接口

2.代理类要实现reflect包里面的接口InvocationHandler

3.通过jdkProxy提供的静态方法newProxyInstance(xxx)动态创建代理类

代理类和被代理类使用同样的对象引用,因此我们可以神不知鬼不觉地使用我们的真实业务类, 而无需关注在它周围的切面逻辑(独立性), 

 

说一下IOC?

loC——Inversion of Control 即“控制反转”,是一种设计思想。在java开发中,loc意味着将你设计好的对象交给容器控制,而不是传统的由对象内部控制。loc通常是由DI实现的,下面我们介绍一下DI。

​ DI------Dependency Injection,即依赖注入,组件之间的依赖关系由容器在运行期决定,即由容器动态地将某个依赖关系注入到组件当中。依赖注入的目的是为了提升组件重用的频率,并为系统搭建一个灵活可扩展的平台。

核心要点:

1.对象依赖于IOC/DI容器,因为对象需要IOC/DI容器来提供对象需要的外部资源。

2.IOC/DI容器注入对象,注入的是某个需要的东西那就是注入对象所需要的资源

3.IOC/DI容器控制对象,主要是控制对象实例的创建

案例:常规情况下的应用程序,如果要在A里面使用C,会去直接去创建C的对象,也就是说,是在A类中主动去获取所需要的外部资源C,这种情况被称为正向的。反向就是A类不再主动去获取C,而是被动等待,等待IoC/DI的容器获取一个C的实例,然后反向的注入到A类中。

 

说一下垃圾回收机制?

GC 的作用区域:

频繁在新生区收集,很少在养老区收集,几乎不在方法区(永久区/元空间)收集,其中,Java堆是垃圾收集器的工作重点

判断对存活的方法:

1.引用计数法

1、引用计数算法(Reference Counting)比较简单,对每个对象保存一个整型的引用计数器属性。用于记录对象被引用的情况。

2、对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1;当引用失效时,引用计数器就减1。只要对象A的引用计数器的值为0,即表示对象A不可能再被使用,可进行回收。

存在一个严重的问题:无法处理循环引用的情况

2.可达性分析算法

该算法的基本思路就是通过一些被称为 引用链(GC Roots)的对象作为起点,从这些节点开始向下搜索,搜索走过的路径被称为(Reference Chain),当一个对象到GC Roots没有任何引用链相连时(即从GC Roots节点到该节点不可达),则证明该对象是不可用的。

相对于引用计数算法而言,可达性分析算法不仅同样具备实现简单和执行高效等特点, 更重要的是该算法可以有效地解决在引用计数算法中循环引用的问题,防止内存泄漏的发生。

垃圾清除算法

1、标记清除算法(Mark-Sweep)

标记阶段是把所有活动对象(可达对象,reachable)都做上标记的阶段。清除阶段是把那些没有标记的对象,也就是非活动对象回收的阶段。

2、标记复制算法(Copying)

将活着的 内存空间分为两块,每次只使用其中一块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中,之后清除正在使用的内存块中的所有对象,交换两个内存的角色,最后完成垃圾回收。

3、标记压缩算法(Mark-Compact)

第一阶段和标记清除算法一样,从根节点开始标记所有被引用对象

第二阶段将所有的存活对象压缩到内存的一端,按顺序排放。之后,清理边界外所有的空间。

 

分代策略

1、年轻代(Young Gen)

1、年轻代特点:区域相对老年代较小,对象生命周期短、存活率低,回收频繁。

2、这种情况 复制算法的回收整理, 速度是最快的。复制算法的效率只和当前存活对象大小有关,因此很适用于年轻代的回收。而复制算法内存利用率不高的问题,通过hotspot中的两个survivor的设计得到缓解。

2、老年代(Tenured Gen)

老年代特点:区域较大,对象生命周期长、存活率高,回收不及年轻代频繁。

这种情况存在大量存活率高的对象,复制算法明显变得不合适。一般是由 标记-清除或者是标记-清除与标记-清除-整理的混合实现。

 

垃圾收集器

新生代收集器使用的收集器:Serial、PraNew、Parallel Scavenge

老年代收集器使用的收集器:Serial Old、Parallel Old、CMS

 

8602adf8a146b44d561da5cc14f2f799.png

Serial收集器(复制算法)

新生代单线程收集器,标记和清理都是单线程,优点是简单高效。

Serial Old收集器(标记-整理算法)

老年代单线程收集器,Serial收集器的老年代版本。

ParNew收集器(停止-复制算法) 

新生代收集器,可以认为是Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现。

Parallel Scavenge收集器(停止-复制算法)

并行多线程收集器,追求高吞吐量,高效利用CPU。吞吐量一般为99%, 吞吐量= 用户线程时间/(用户线程时间+GC线程时间)。适合后台应用等对交互相应要求不高的场景。

Parallel Old收集器(停止-复制算法)

Parallel Scavenge收集器的老年代版本,并行收集器,吞吐量优先,使用多线程。

CMS(Concurrent Mark Sweep)收集器(标记-清理算法)

高并发、低停顿,追求最短GC回收停顿时间,cpu占用比较高,响应时间快,停顿时间短,多核cpu 追求高响应时间的选择。

无法清理浮动垃圾,容易产生碎片。

清理过程分为4个步骤,包括:

  1. 初始标记(CMS initial mark)
  2. 并发标记(CMS concurrent mark)
  3. 重新标记(CMS remark)
  4. 并发清除(CMS concurrent sweep)

G1收集器

并行与并发执行,分代收集,空间整合,分为不同的regin区域进行垃圾回收

G1 收集器的运作大致可划分为以下几个步骤:

  1. 初始标记(Initial Marking)
  2. 并发标记(Concurrent Marking)
  3. 最终标记(Final Marking)
  4. 筛选回收(Live Data Counting and Evacuation)

 

Minor GC(新生代GC):

指发生在新生代的垃圾收集动作,Java对象大多存活时间不长,所以Minor GC的发生会比较频繁,回收速度也比较快。触发条件:在新生代的Eedn区满了会触发。

Full GC/Major GC(老年代GC):

指发生在老年代的GC,出现了Full GC,经常会伴随至少一次的Minor GC(不是必然的),Major GC的速度一般会比Minor GC慢10倍以上。

触发条件:

System.gc() 方法的调用,此方法会建议JVM进行Full GC,但JVM可能不接受这个建议,所以不一定会执行。

老年代空间不足,创建的大对象的内存大于老年代空间,导致老年代空间不足,则会发生Full GC。

JDK1.7及以前的永久代空间满了,在JDK1.7以前,HotSpot虚拟机的方法区是永久代实现都得,在永久代中会存放一些Class的信息、常量、静态变量等数据,在永久代满了,并且没有配置CMS GC的情况下就会触发Full GC,在JDK1.8开始移除永久代也是为了减少Full GC的频率。

空间分配担保失败,通过Minor GC后进入老年代的平均大小大于老年代的可用空间,会触发Full GC

 

内存回收机制

对象先在Eden区分配,当Eden区没有足够的空间去分配时,虚拟机会发起一次Minor GC,将存活的对象放到From Survivor区(对象年龄为1)。

当再次发生Minor GC,会将Eden区和From Survivor区一起清理,存活的对象会被移动到To Survivor区(年龄加1)。

这时From Survivor区会和To Survivor区进行交换,然后重复第一步,不过这次第一步中的From Survivor区其实是上一轮中的To Survivor区。

每次移动,对象的年龄就会加1,当年龄到达15时(默认是15,对象晋升老年代的年龄阈值可以通过参数 -XX: MaxTenuringThreshold 设置),会从新生代进入老年代。

 

总结:

1.对象优先在Eden区分配。

2.大对象直接进入老年代(大对象指需要大量连续内存空间的Java对象)。

3.长期存活的对象进入老年代。

 

讲一下布隆过滤器?

它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。

布隆过滤器可以告诉我们 “某样东西一定不存在或者可能存在”

 

业务场景:

解决Redis缓存穿透问题(面试重点)

邮件过滤,使用布隆过滤器来做邮件黑名单过滤

对爬虫网址进行过滤,爬过的不再爬

解决新闻推荐过的不再推荐(类似抖音刷过的往下滑动不再刷到)

 

如何解决缓存击穿问题?

方案一、定时任务主动刷新缓存设计

先将所有可能查询到的数据存入redis,对redis中的数据库定时更新,保证redis永远都会有数据存在,来请求只查redis

 

方案二、使用redis的分布式锁

具体步骤:

1.如果缓存命中直接返回数据集

2.如果缓存没有,则尝试获取分布式锁(有超时设置)如果没有拿到锁,则阻塞当前线程,n秒之后再次尝试获取分布式锁

3.拿到锁之后检查数据是否已经被其他线程放到redis缓存中,如果redis缓存已有,直接返回redis中的数据,释放分布式锁;如果缓存没有被刷新,则查数据库将数据库查询的结果保存到redis缓存中并返回查询结果

 

方案三、普通加jvm的锁查询缓存

如果缓存命中直接返回数据集

如果缓存没有,则尝试JVM锁,

其他线程阻塞拿到锁之后,检查redis是否有数据,以免其他线程已经刷过缓存

如果redis已经有数据,直接返回,并释放锁,返回数据库结束

如果redis没有数据,则查询数据库,并保存到redis缓存中返回数据,释放锁

 

比如:

有s台服务器,用户请求数为n;那么同一时间参数相同的请求最多只会有s次查询打到数据库上,这里s这个常量相当于原来对于数据库来说一个O(n)的操作时间下降到了O(s)

这里可以看出,查询数据库操作的耗时与n的增长无关,只与s有关

 

方案四、jvm缓存+redis缓存的多级缓存

 

1ab3d3eae53d0227758a97db8d49ce4b.png

这种设计,服务器只会在jvm缓存失效,且redis缓存也失效的情况下才会查询数据库,而多个服务器的jvm缓存失效时间是随机值,所以很大程度上避免的同时失效去查库的情况,由于所有服务器jvm缓存同时失效redis缓存也失效的可能性极低,所以数据库上重复的查询会很少

 

如何优化sql查询速度

1.添加索引

经常需要搜索的列上,可以加快搜索的速度;

在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。

在经常需要排序的列上创 建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;

对于中到大型表索引都是非常有效的,但是特大型表的话维护开销会很大,不适合建索引

在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;

避免 where 子句中对宇段施加函数,这会造成无法命中索引。

2.实现细节

1.SQL语句中IN包含的值不应过多;

2.SELECT语句务必指明字段名称,不用*;

3.只查询一条数据的时候,使用limit 1;

4.避免在where子句中对字段进行表达式操作,这样做可能导致索引失效;

5.对于联合索引来说,要遵守最左前缀法则,防止其失效;

6.尽量使用inner join,这样在没有其他过滤条件的情况下MySQL会自动选择小表作为驱动表;

7.对于联合索引来说,如果存在范围查询,比如between、>、<等条件时,会造成后面的索引字段失效。

解决办法: 业务允许的情况下,使用 >= 或者<=  这样不影响索引的使用.;

8.在 where 子句中使用 or 来连接条件,如果or连接的条件有一方没有索引,将导致引擎放弃使用索引而进行全表扫描

解决办法: 将or连接的双方都建立索引,就可以使用. 

9.count 优化     速度:count(*)>count(1)>count(字段)

10.指定查询的索引

use index(索引): 推荐使用指定的索引 (最终用不用该索引,还需要mysql自己判断)

ignore index(索引) : 忽略掉这个索引

force index(索引): 强制使用该索引

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/293395.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

NVIDIA 正式发布中国特供 RTX 4090D,减量不减价刀法再进化

随着中国特供 RTX 4090D 显卡发布&#xff0c;老美禁售导致的 NVIDIA 旗舰游戏显卡断供、涨价风波注定要结束了。 就在上周四&#xff0c;NVIDIA 正式发布了应对老美禁令的中国特供版 RTX 4090D 显卡。 别的不说&#xff0c;前段时间疯狂炒作、高价囤货 RTX 4090 的商贩们首先…

在机械硬盘和固态硬盘上分别打一个压缩包,时间相差几倍

机械硬盘&#xff0c;它的原理类似于光盘&#xff0c;主要结构是一个高速旋转的盘片的和在盘片上来回读写数据的磁头。而固态硬盘则是以电子存储的方式来储存数据的&#xff0c;主要由主控芯片、闪存芯片、固件算法等组成。 一般来说机械硬盘的读写速度在60-170MB/s之间&#x…

win10提示“KBDROST.DLL文件丢失,软件无法启动”,快速修复方法

KBDROST.DLL是Windows操作系统中的一个动态链接库文件&#xff0c;主要与键盘布局或键盘输入有关。在Windows系统中&#xff0c;每种语言都有一个相应的DLL文件来处理键盘输入&#xff0c;KBDROST.DLL文件主要用于处理俄语键盘布局。 所以&#xff0c;当我们使用到俄语输入相关…

Linux第12步_磁盘重新分区

解决“挂载后的U盘出现中文乱码”后&#xff0c;我们接着学习“磁盘重新分区”&#xff0c;熟悉fdisk命令。 1、删除磁盘的分区 输入“cd /回车”&#xff0c;进入根目录 输入“ls /dev/sd*回车”&#xff0c;显示dev以sd所有文件。 输入“sudo fdisk /dev/sdb1回车” 输入…

学习汽车LIN总线该如何入门?

关注菲益科公众号—>对话窗口发送 “CANoe ”或“INCA”&#xff0c;即可获得canoe入门到精通电子书和INCA软件安装包&#xff08;不带授权码&#xff09;下载地址。 目录 1. 车载LIN总线诞生背景和使用场景 2. LIN总线硬件接口 3. Lin总线协议 4. 总结 1、车载LIN总线…

北斗卫星为社区智慧管理提供精准支持

北斗卫星为社区智慧管理提供精准支持 近年来&#xff0c;随着智能科技的快速发展和智慧社区的兴起&#xff0c;北斗卫星作为一项关键技术&#xff0c;正逐渐在智慧社区中发挥着重要作用。北斗卫星定位与导航系统是我国自主研发的卫星导航定位系统&#xff0c;它不仅为智慧社区…

postgresql可视化导入csv文件

不需要在命令行copy了&#xff0c;只需简单点几下 1.在数据库下建一个schema 右击选中数据库-new schema 2.双击你创建的schema&#xff0c;出现tables 3.右击tables&#xff0c;选择import wizard 4.选择你想导入的文件格式&#xff0c;之后一直next 5.选择你的文件所在位置…

工厂如何确定设备故障的原因?

设备故障是制造业中常见的问题&#xff0c;对生产效率和运营成本产生重大影响。为了解决设备故障并提高生产效率&#xff0c;确定设备故障的准确原因至关重要。本文将介绍一些关键步骤和方法&#xff0c;帮助工厂确定设备故障的原因。 1. 收集和分析数据 要确定设备故障的原因…

HTTP和TCP代理原理及实现,主要是理解

Web 代理是一种存在于网络中间的实体&#xff0c;提供各式各样的功能。现代网络系统中&#xff0c;Web 代理无处不在。我之前有关 HTTP 的博文中&#xff0c;多次提到了代理对 HTTP 请求及响应的影响。今天这篇文章&#xff0c;我打算谈谈 HTTP 代理本身的一些原理&#xff0c;…

【自学笔记】01Java基础-07面向对象基础-02继承

记录学习Java基础中有关继承、方法重写、构造器调用的基础知识&#xff0c;学习继承之前建议学习static关键字的内容【自学笔记】01Java基础-09Java关键字详解 1 继承概述 1.1 什么是继承&#xff1f; 1.2 继承的特点 子类可以继承父类的属性和行为&#xff0c;但是子类不能…

期货跟单系统。镜像跟单系统有什么作用?功能有哪些?

期货跟单系统&#xff1a; 期货自动跟单系统&#xff0c;是一款专门用来针对特定账户的操作而进行自动跟单的软件。软件兼容目前所有的期货公司账户&#xff0c;具有稳定性&#xff0c;速度性和可靠性的优势。 补差补点&#xff0c;根据盘手实盘心理分析&#xff0c;增加模拟…

PLC三相电动机Y-▲启动控制程序示例

一、三相电动机星三角启动接法。 二、因为电动机在启动的时候启动电流非常的大&#xff0c;所以在启动时采用星型接法&#xff0c;也就是Y型接法&#xff0c;也就是图上的KM1和KM2接通&#xff0c;目的为了减小启动电流&#xff0c;采用Y型接法的启动电流是原来电流的1/3 三、启…

华为交换机怎么添加和剥除VLAN标签

知识改变命运&#xff0c;技术就是要分享&#xff0c;有问题随时联系&#xff0c;免费答疑&#xff0c;欢迎联系&#xff01; 华为交换机VLAN标签的添加和剥除处理过程 接口对收发的以太网数据帧添加或剥除VLAN标签的处理依据接口的接口类型和缺省VLAN。 由上面各类接口添加或…

Mybatis之多表查询

目录 一、简介 1、使用嵌套查询: 2、使用多个 SQL 语句&#xff1a; 3、使用关联查询&#xff1a; 4、使用自定义映射查询&#xff1a; 二、业务场景 三、示例 1、一对一查询 2、一对多查询 一、简介 MyBatis 是一个优秀的持久层框架&#xff0c;它提供了强大的支持来执…

小样本学习介绍(超详细)

小样本学习介绍 本文首先介绍了什么是小样本学习&#xff0c;其次介绍了为什么小样本学习的很多文章都采用元学习的方法。目的是通过通俗的解释更加清楚的介绍小样本学习是什么&#xff0c;适合初学者的入门。当然&#xff0c;以下更多的是自己的思考&#xff0c;欢迎交流。 …

cesium第一视角/上帝视角以及解除视角锁定

第一视角效果&#xff1a; function event1() {viewer.scene.screenSpaceCameraController.enableZoom false; //. 禁止视角缩放viewer.scene.screenSpaceCameraController.enableRotate false; //禁止左键拖动视角viewer.scene.screenSpaceCameraController.enableTilt fal…

GAMES101:作业5记录

总览 在这部分的课程中,我们将专注于使用光线追踪来渲染图像。在光线追踪中最重要的操作之一就是找到光线与物体的交点。一旦找到光线与物体的交点,就可以执行着色并返回像素颜色。在这次作业中,我们需要实现两个部分:光线的生成和光线与三角的相交。本次代码框架的工作流程为…

【C语言】stdbool.h——有关bool的总结

在编程和日常生活中&#xff0c;经常需要一种只能具有两个值之一的数据类型&#xff0c;如是否、开关、真假等&#xff0c;因此&#xff0c;C 有一种bool数据类型&#xff0c;称为booleans。布尔值表示 或true的值false。 C 中的 bool 是大多数语言中的基本数据类型&#xff0…

自由DIY预约小程序源码系统:适用于任何行业+自由DIY你的界面布局+全新升级的UI+多用户系统 带安装部署教程

随着移动互联网的普及&#xff0c;预约服务逐渐成为人们日常生活的一部分。从家政服务、医疗挂号到汽车保养&#xff0c;预约已经渗透到各个行业。然而&#xff0c;市面上的预约小程序大多功能单一&#xff0c;界面老旧&#xff0c;无法满足商家和用户的个性化需求。今天来给大…

03 decision tree(决策树)

一、decision tree&#xff08;决策树&#xff09; 1. classification problems&#xff08;纯度&#xff09; i . entropy &#xff08;熵&#xff09; ​ 作用&#xff1a;衡量一组数据的纯度是否很纯 &#xff0c;当五五开时他的熵都是最高的&#xff0c;当全是或者都不是…