美团后端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

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缓存的多级缓存

这种设计,服务器只会在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(索引): 强制使用该索引

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python中property特性属性是什么

在Java中&#xff0c;通常在类中定义的成员变量为私有变量&#xff0c;在类的实例中不能直接通过对象.属性直接操作&#xff0c;而是要通过getter和setter来操作私有变量。 而在Python中&#xff0c;因为有property这个概念&#xff0c;所以不需要写getter和setter一堆重复的代…

当你遇到这些情况的时候,发版到白了少年头,代码还是不会更新...

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 一、问题描述&#xff1a; 之前遇到过几次这种情况&#xff1a;研发将代码提交之后&#xff0c;通过打包部署&#xff0c;发现部…

K8S容器的一则故障记录

一、故障现象 XXX反馈说某某业务服务异常&#xff0c;无法启动&#xff0c;需要进行协助排查。经常会接到这样一个需求&#xff0c;一开始无法清楚知道具体什么问题&#xff0c;需要跟一线运维人员详细做沟通&#xff0c;了解故障问题的细节。 根据一线运维人员的反馈&#xff…

听GPT 讲Rust源代码--src/tools(36)

File: rust/src/tools/clippy/clippy_lints/src/loops/empty_loop.rs 在Rust源代码中&#xff0c;empty_loop.rs文件位于src/tools/clippy/clippy_lints/src/loops/目录下&#xff0c;它的作用是实现并提供一个名为EMPTY_LOOP的Lint规则。Clippy是一个Rust的静态分析工具&#…

个人财务管理软件Money Pro mac功能特点

Money Pro mac是一款专为Mac用户设计的个人财务管理软件&#xff0c;具有全面的账户管理、智能的预算规划、强大的投资分析、丰富的报表和图表、安全的数据保护以及易于使用的界面设计等特点。 Money Pro mac功能和特点 全面的账户管理&#xff1a;支持多种账户类型&#xff0…

Spring Boot 基于Redisson实现注解式分布式锁

依赖版本 JDK 17 Spring Boot 3.2.0 Redisson 3.25.0 源码地址&#xff1a;Gitee 导入依赖 <properties><redisson.version>3.25.0</redisson.version> </properties><dependencies><dependency><groupId>org.projectlombok</…

CLion中使用C/C++ Single File Execution插件编译和运行单个文件

在开发C/C程序时&#xff0c;尽管项目通常以组织良好的结构进行管理&#xff0c;但有时我们可能只需要快速测试或运行单个C或C源文件。对于这种情况&#xff0c;JetBrains CLion IDE提供了一个便捷的解决方案——通过安装名为“C/C Single File Execution”的插件来实现对单个源…

【OpenCV】OpenCV 4.9.0 正式发布

​ 开源计算机视觉库 OpenCV 4.9.0 已于2023年12月29日正式发布。 此次发布有DNN模块对ONNX Attention、Einsum等层的支持、新的fastGEMM实现、transformers的实验性支持等诸多亮点。 OpenCV 4.9.0 更新内容&#xff1a; &#xff08;来自OpenCV中国团队以及中国社区的贡献…

antv/x6_2.0学习使用(二、画布)

画布 一. 创建容器 在页面中创建一个 div 标签&#xff0c;用来容纳画布 <div id"container"></div>画布常用配置信息 const graph new Graph({container: graphRef.value, // 画布容器width: 800, // 画布宽度&#xff0c;默认使用容器宽度height:…

2017年喜茶数字营销变化

1. 什么是数字营销&#xff1f;数字化时代&#xff0c;消费者行为模式发生了哪些变化&#xff1f; 数字营销是指使用数字渠道和平台&#xff0c;通过在线手段推广产品或服务&#xff0c;与目标受众进行互动和沟通的一种营销方式。它涵盖了多种在线渠道&#xff0c;包括社交媒…

华为云云耀云服务器L实例评测|Python Selenium加Chrome Driver构建UI自动化测试实践

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;AWS/阿里云资深使用…

HackTheBox - Medium - Linux - Bagel

Bagel 今天我开始了《Red Team Development and Operations A Practical Guide》的学习&#xff0c;保持学习&#xff0c;后面差不多到时机后就学CRTOⅡ Bagel 是一款中等难度的 Linux 机器&#xff0c;其特点是电子商店容易受到路径遍历攻击&#xff0c;通过该攻击可以获取应…

使用vmware,在ubuntu18.04中使用笔记本的摄像头

步骤1&#xff1a;在windows中检查相机状态 win10系统中&#xff0c;在左下的搜索栏&#xff0c;搜索“相机”&#xff0c;点击进入即可打开相机&#xff0c;并正常显示图像。 注意&#xff1a;如果相机连接到了虚拟机&#xff0c;则不能显示正常。 步骤2&#xff1a;在ubuntu…

STM32——通用计时器

通用计时器框图 1.时钟源 1&#xff09;内部时钟(CK_INT) 2&#xff09;外部时钟模式 1&#xff1a;外部输入引脚(TIx)&#xff0c;x1&#xff0c;2&#xff08;即只能来自于通道 1 或者通道 2&#xff09; 3&#xff09;外部时钟模式 2&#xff1a;外部触发输入(ETR) 4&#…

ARCGIS PRO SDK 访问Geometry对象

一、Geometry常用对象 二、主要类 1、ReadOnlyPartCollection&#xff1a;Polyline 和 Polygon 使用的 ReadOnlySegmentCollection 部件的只读集合&#xff0c;属性成员&#xff1a;​ 名字描述Count获取 ICollection 中包含的元素数。TIEM获取位于指定索引处的元素。Spatial…

mac中excel条件格式找到每一列的最大值并标红

假设现在excel有A1:R24组数据&#xff0c;最终效果如下 先选择要处理数据的第一列&#xff0c;然后点击【条件格式】-【新建规则】 style选择【classic】以及【Use a formula to determine which cells to format】&#xff0c;输入规则【C3MAX(C$3:C$24)】 注意这里C$3前面没…

Rust开发⼲货集(1)--迭代器与消费器

本内容是对 Rust开发干货集[1] 的实践与扩展. iter() 不转移所有权 先简单解释下什么叫"转移所有权": 在 Rust 中&#xff0c;"转移所有权"&#xff08;Ownership Transfer&#xff09;是一种核心概念&#xff0c;它涉及变量和数据的所有权从一个实体转移…

3D视觉-结构光测量-线结构光测量

概述 线结构光测量中&#xff0c;由激光器射出的激光光束透过柱面透镜扩束&#xff0c;再经过准直&#xff0c;产生一束片状光。这片光束像刀刃一样横切在待测物体表面&#xff0c;因此线结构光法又被成为光切法。线结构光测量常采用二维面阵 CCD 作为接受器件&#xff0c;因此…

QT上位机开发(乘法计算小软件)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面一篇文章&#xff0c;我们学习了怎么创建qt的第一个工程&#xff0c;怎么用designer给qt修改界面。虽然我们到目前为止&#xff0c;还没有编写…

C#使用switch语句更改窗体颜色

目录 一、示例 二、生成 用switch多路选择语句及窗体的BackColor属性更改窗体的BackColor属性。该属性用于获取或设置控件的背景颜色。 可以使用Color结构的静态属性获取Color对象&#xff0c;如Color.Red&#xff1b;也可以使用Color结构的静态方法Color.FromArgb()&#xf…