1.什么时候重写equals和hashCode方法?

 /*因为Object中默认的equals方法,内部还是使用==来比较对象在内存中的地址,所以结果位false*//*如果重写了equals方法,那么如果两个对象的属性值相同,那么程序会在第三步判断中返回true,* hashCode()方法,它是一个本地方法,底层是运用对象的内存地址通过哈希函数来计算的。* 问题:为什么重写equals时,一定需要重写hashCode()方法?* 因为重写了equals()之后,判断两个属性值相同的对象时,会返回true,如果没有重写hashCode(),* 那么程序还是按照默认的使用内存地址的方法去计算,那么一定会返回false,* java中规定:两个对象的equals()相同,hashCode一定相同。hashCode相同,但equals不一定相同* 所以在重写equals时,一定需要重写hashCode。*//*什么时候需要重写类的equals()和hashCode()方法?* 1.当我们需要重新定义两个对象是否相等的条件时,需要进行重写。比如通常情况下,我们认为两个不同对象的某些属性值相同时,* 就认为这两个对象是相同的。* 例如:我们在HashMap中添加元素时,我们认为当key相同时,两个元素就相同,但是默认的Object中的equals(),只是单纯的比较两个元素  的内存地址是否相同,不能满足我们的要求,所以需要重写。* 2.当我们自定义一个类时,想要把它的实例保存在集合时,就需要重写equals()和hashCode()方法。*/

2.java集合继承结构,for和iterator遍历中删除元素有什么问题?

for循环删除ArrayList中的某个值

    
public static void main(String[] args) {ArrayList<Integer> arrayList = new ArrayList<>();arrayList.add(1);arrayList.add(1);arrayList.add(2);arrayList.add(2);arrayList.add(3);arrayList.add(4);/*** 正序搜索删除*/for (int i = 0; i <arrayList.size()-1;i++) {if(arrayList.get(i).equals(1)){arrayList.remove(i);}}System.out.println("正序"+arrayList);/*** 反序搜索删除*/for (int i = arrayList.size()-1; i >=0; i--) {if(arrayList.get(i).equals(2)){arrayList.remove(i);}}System.out.println("反序"+arrayList);}​

执行结果如下:

正序:[1,2,2,3,4]
反序:[1,3,4]

可以发现正序删除并没能删除所有的1,而反序则可以完全删除所有的2。

因为ArrayList删除一个元素后,所有的元素都会向前移动,所以就会导致连续的1,并没能完全删掉。而后序遍历,删除,并不会影响前一个节点的值,所以可以完全删除。

Iterator删除ArrayList中的某个值

 package com;​import java.util.ArrayList;import java.util.Iterator;​public class remove {​public static void main(String[] args) {ArrayList<Integer> arrayList = new ArrayList<>();arrayList.add(1);arrayList.add(1);arrayList.add(2);arrayList.add(2);arrayList.add(3);arrayList.add(4);/*** arrayList删除*/Iterator<Integer> iterator = arrayList.iterator();try {while(iterator.hasNext()){Integer next = iterator.next();if(next.equals(1)){arrayList.remove(next);}}} catch (Exception e) {e.printStackTrace();}System.out.println(arrayList);/*** iterator删除*/Iterator<Integer> iterator2 = arrayList.iterator();while (iterator2.hasNext()) {Integer next =  iterator2.next();if(next.equals(2)){iterator2.remove();}}System.out.println(arrayList);}​}​

执行结果如下:

可以发现上面的iterator使用ArrayList删除第一个元素1的时候,删除成功了,但是在删除第二之前时候(不是其没能力删除),好像就报了ConcurrentModificationException的错误。

而下面的iterator删除集合元素的方法就成功了,并不会报错。

可以发现,当在使用ArrayList删除后,modCount就会发生改变,期待的值不是6了,于是这里产生了异常,故抛出异常

而对于iterator的remove方法:

可以发现,其调用的虽然是ArrayList的删除方法,但它在后面更新了新的expectedModCount,使得每次两个都能相等,这样就不会抛出异常了。能正常执行下去。

3.线程有哪几种状态?阻塞(BLOCK)?如何终止线程?

 线程的五种状态:1.新建(new)创建了一个新的线程对象​2.就绪(runnable)​调用线程的start()方法,处于就绪状态​3.运行(running)​获得了CPU时间片,执行程序代码​就绪状态是进入到运行状态的唯一入口​4.阻塞(block)​因为某种原因,线程放弃对CPU的使用权,停止执行,直到进入就绪状态在有可能再次被CPU调度​阻塞又分为三种:​1)等待阻塞:运行状态的线程执行wait方法,JVM会把线程放在等待队列中,使本线程进入阻塞状态。2)同步阻塞:线程在获得synchronized同步锁失败,JVM会把线程放入锁池中,线程进入同步阻塞。3)其他阻塞:调用线程的sleep()或者join()后,线程会进入道阻塞状态,当sleep超时或者join终止或超时,线程重新转入就绪状态​5.死亡(dead)​线程run()、main()方法执行结束,或者因为异常退出了run()方法,则该线程结束生命周期​死亡的线程不可再次复生

join方法详解:

前面几篇文章讲解了wait()方法之后,我们再来讲讲join()方法,因为join()方法就是通过wait()方法实现的。

join()方法的作用:让主线程等待(WAITING状态),一直等到其他线程不再活动为止。

join在英语中是“加入”的意思,join()方法要做的事就是,当有新的线程加入时,主线程会进入等待状态,一直到调用join()方法的线程执行结束为止。

4.如何面对缓存穿透,缓存击穿,缓存雪崩,怎么解决?

5.在一个分布式系统场景下面,如何设置唯一主键

如何在分布式场景下生成全局唯一 ID ? - 腾讯云开发者社区-腾讯云 (tencent.com)

6.如何避免下单接口重复接单

【干货】如何防止接口重复提交?(中) - 腾讯云开发者社区-腾讯云 (tencent.com)

即如何实现接口幂等性:阿里面试官:接口的幂等性怎么设计? - 知乎 (zhihu.com)

方案一:

下面我们以防止重复提交订单为例,向大家介绍最简单的、成本最低的解决办法

我们先来看一张图,这张图就是本次方案的核心流程图。

实现的逻辑,流程如下:

  • 1.当用户进入订单提交界面的时候,调用后端获取请求唯一ID,并将唯一ID值埋点在页面里面

  • 2.当用户点击提交按钮时,后端检查这个唯一ID是否用过,如果没有用过,继续后续逻辑;如果用过,就提示重复提交

  • 3.最关键的一步操作,就是把这个唯一ID 存入业务表中,同时设置这个字段为唯一索引类型,从数据库层面做防止重复提交

方案二:

随着业务的快速增长,每一秒的下单请求次数,可能从几十上升到几百甚至几千。

面对这种下单流量越来越高的场景,此时数据库的访问压力会急剧上升,上面这套方案全靠数据库来解决,会特别吃力!

对于这样的场景,我们可以选择引入缓存中间件来解决,可选的组件有 redis、memcache 等。

下面,我们以引入redis缓存数据库服务器,向大家介绍具体的解决方案!

实现的逻辑,流程如下:

  • 1.当用户进入订单提交界面的时候,调用后端获取请求唯一 ID,同时后端将请求唯一ID存储到redis中再返回给前端,前端将唯一 ID 值埋点在页面里面

  • 2.当用户点击提交按钮时,后端检查这个请求唯一 ID 是否存在,如果不存在,提示错误信息;如果存在,继续后续检查流程

  • 3.使用redis的分布式锁服务,对请求 ID 在限定的时间内进行加锁,如果加锁成功,继续后续流程;如果加锁失败,说明服务正在处理,请勿重复提交

  • 4.最后一步,如果加锁成功后,需要将锁手动释放掉,以免再次请求时,提示同样的信息;同时如果任务执行成功,需要将redis中的请求唯一 ID 清理掉

  • 5.至于数据库是否需要增加字段唯一索引,理论上可以不用加,如果加了更保险

方案三:

每次提交的时候,需要先调用后端服务获取请求唯一ID,然后才能提交。

对于这样的流程,不少的同学可能会感觉到非常鸡肋,尤其是单元测试,需要每次先获取submitToken值,然后才能提交!

能不能不用这么麻烦,直接服务端通过一些规则组合,生成本次请求唯一ID呢

答案是可以的!

今天我们就一起来看看,如何通过服务端来完成请求唯一 ID 的生成?

实现的逻辑,流程如下:

  • 1.用户点击提交按钮,服务端接受到请求后,通过规则计算出本次请求唯一ID值

  • 2.使用redis的分布式锁服务,对请求 ID 在限定的时间内尝试进行加锁,如果加锁成功,继续后续流程;如果加锁失败,说明服务正在处理,请勿重复提交

  • 3.最后一步,如果加锁成功后,需要将锁手动释放掉,以免再次请求时,提示同样的信息

7.Redis 过期键的的删除策略?

其实有三种不同的删除策略: (1):立即删除。在设置键的过期时间时,创建一个回调事件,当过期时间达到时,由时间处理器自动执行键的删除操作。 (2):惰性删除。键过期了就过期了,不管。每次从dict字典中按key取值时,先检查此key是否已经过期,如果过期了就删除它,并返回nil,如果没过期,就返回键值。 (3):定时删除。每隔一段时间,对expires字典进行检查,删除里面的过期键。 可以看到,第二种为被动删除,第一种和第三种为主动删除,且第一种实时性更高。下面对这三种删除策略进行具体分析。

具体介绍:

立即删除

立即删除能保证内存中数据的最大新鲜度,因为它保证过期键值会在过期后马上被删除,其所占用的内存也会随之释放。但是立即删除对cpu是最不友好的。因为删除操作会占用cpu的时间,如果刚好碰上了cpu很忙的时候,比如正在做交集或排序等计算的时候,就会给cpu造成额外的压力。

而且目前redis事件处理器对时间事件的处理方式–无序链表,查找一个key的时间复杂度为O(n),所以并不适合用来处理大量的时间事件。

惰性删除

惰性删除是指,某个键值过期后,此键值不会马上被删除,而是等到下次被使用的时候,才会被检查到过期,此时才能得到删除。所以惰性删除的缺点很明显:浪费内存。dict字典和expires字典都要保存这个键值的信息。

举个例子,对于一些按时间点来更新的数据,比如log日志,过期后在很长的一段时间内可能都得不到访问,这样在这段时间内就要拜拜浪费这么多内存来存log。这对于性能非常依赖于内存大小的redis来说,是比较致命的。

定时删除

从上面分析来看,立即删除会短时间内占用大量cpu,惰性删除会在一段时间内浪费内存,所以定时删除是一个折中的办法。 定时删除是:每隔一段时间执行一次删除操作,并通过限制删除操作执行的时长和频率,来减少删除操作对cpu的影响。另一方面定时删除也有效的减少了因惰性删除带来的内存浪费。

8.SQL语句,A、B两表,找出ID字段中,存在 EA表,但是不存在B表的数据

  • 使用 not in ,容易理解,效率低 执行时间为:1.395秒

 select distinct A.ID from A where A.ID not in (select ID from B)
  • 使用 left join…on… , “B.ID isnull” 表示左连接之后在B.ID 字段为 null的记录 执行时间:0.739秒

 select A.ID from A left join B on A.ID=B.ID where B.ID is null
  • 逻辑相对复杂,但是速度最快 ~执行时间: 0.570秒~

 select * from B where (select count(1) as num from A where A.ID = B.ID) = 0

(说实话,没太理解最后一种方法~)

注意:

COUNT函数的用法,主要用于统计表行数。主要用法有COUNT(*)COUNT(字段)COUNT(1)

因为COUNT(*)是SQL92定义的标准统计行数的语法,所以MySQL对他进行了很多优化,MyISAM中会直接把表的总行数单独记录下来供COUNT(*)查询,而InnoDB则会在扫表的时候选择最小的索引来降低成本。当然,这些优化的前提都是没有进行where和group的条件查询。

在InnoDB中COUNT(*)COUNT(1)实现上没有区别,而且效率一样,但是COUNT(字段)需要进行字段的非NULL判断,所以效率会低一些。

因为COUNT(*)是SQL92定义的标准统计行数的语法,并且效率高,所以请直接使用COUNT(*)查询表的行数!

9.MySQL索引类型有哪些?联合索引的应用?

  • PRIMARY KEY 主键索引

  • INDEX 普通索引

  • UNIQUE 唯一索引

  • FULLTEXT 全文索引

  • 组合/联合索引(较特殊)

具体介绍:

主键索引:主键是一种唯一性索引,每个表只能有一个主键,在单表查询中,PRIMARY主键索引与UNIQUE唯一索引的检索效率并没有多大的区别,

但在关联查询中,PRIMARY主键索引的检索速度要高于UNIQUE唯一索引。

普通索引:这是最基本的索引类型,而且它没有唯一性之类的限制。

唯一索引:这种索引和前面的“普通索引”基本相同,但有一个区别:索引列的所有值都只能出现一次,即必须唯一。

全文索引:MySql从3.23版开始支持全文索引和全文检索。全文索引只可以在VARCHAR或者TEXT类型的列上创建。

联合索引 (也叫组合索引、复合索引、多列索引)是指对表上的多个列进行索引

联合索引又叫复合索引。对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。例如索引是key index (a,b,c). 可以支持a | a,b| a,b,c 3种组合进行查找,但不支持 b,c进行查找 .当最左侧字段是常量引用时,索引就十分有效。创建复合索引时,应该仔细考虑列的顺序。对索引中的所有列执行搜索或仅对前几列执行搜索时,复合索引非常有用;仅对后面的任意列执行搜索时,复合索引则没有用处。

联合索引的应用:

应用场景一:SQL查询列很少,建立查询列的联合索引可以有效消除回表,但一般超过3个字段的联合索引都是不合适的.

应用场景二:在字段A返回记录多,在字段B返回记录多,在字段A,B同时查询返回记录少,比如执行下面的查询,结果c1,c2都很多,c3却很少。

 select count(1) c1 from t where A = 1; select count(1) c2 from t where B = 2; select count(1) c3 from t where A = 1 and B = 2; 

其他应用:

 (1) select * from mytable where a=3 and b=5 and c=4;# abc 三列都使用索引,而且都有效​(2) select * from mytable where  c=4 and b=6 and a=3;# mysql没有那么笨,不会因为书写顺序而无法识辨索引。# where里面的条件顺序在查询之前会被mysql自动优化,效果跟上一句一样。​(3) select * from mytable where a=3 and c=7;# a 用到索引,sql中没有使用 b列,b列中断,c没有用到索引​(4) select * from mytable where a=3 and b>7 and c=3;# a 用到索引,b也用到索引,c没有用到。# 因为 b是范围索引,所以b处断点,复合索引中后序的列即使出现,索引也是无效的。​(5) select * from mytable where b=3 and c=4;# sql中没有使用a列, 所以b,c 就无法使用到索引​(6) select * from mytable where a>4 and b=7 and c=9;# a 用到索引, a是范围索引,索引在a处中断, b、c没有使用索引​(7) select * from mytable where a=3 order by b;# a用到了索引,b在结果排序中也用到了索引的效果。前面说过,a下面任意一段的b是排好序的​(8) select * from mytable where a=3 order by c;# a 用到了索引,sql中没有使用 b列,索引中断,c处没有使用索引,在 Extra列 可以看到 filesort​(9) select * from mytable where b=3 order by a;# 此sql中,先b,后a,导致 b=3 索引无效,排序a也索引无效。​​

索引的危害

表上有过多索引主要会严重影响插入性能;

  • 对delete操作,删除少量数据索引可以有效快速定位,提升删除效率,但是如果删除大量数据就会有负面影响;

  • 对update操作类似delete,而且如果更新的是非索引列则无影响。

10.Http的请求调用过程、协议?

链接:一次完整的HTTP请求过程是怎么样的呢?【图文详解】 - 知乎 (zhihu.com)

具体步骤:

  1. 浏览器进行DNS域名解析,得到对应的IP地址

  2. 根据这个IP,找到对应的服务器建立连接(三次握手)

  3. 建立TCP连接后发起HTTP请求(一个完整的http请求报文)

  4. 服务器响应HTTP请求,浏览器得到html代码(服务器如何响应)

  5. 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等)

  6. 浏览器对页面进行渲染呈现给用户

  7. 服务器关闭TCP连接(四次挥手)

11.fullGC问题如何排查、程序OOM是否还能继续执行

排查:

1.首先我们可以使用top命令查看系统CPU的占用情况

2.接下来我们可以通过jstack命令查看线程id为X的线程为什么耗费CPU最高

3.如果发现full gc数量不断增长,进一步证实了是由于内存溢出导致的系统缓慢。那么这里确认了内存溢出,但是如何查看你是哪些对象导致的内存溢出呢,这个可以dump出内存日志,然后通过eclipse的mat工具进行查看

4.经过mat工具分析之后,我们基本上就能确定内存中主要是哪个对象比较消耗内存,然后找到该对象的创建位置,进行处理即可

OOM后是否运行?

  1. OutOfMemoryError是可以catch的。 catch之后吞掉的话程序还能试着继续运行。

    • OOM的机制决定了这不一个单进程的状态,系统会选择一些可能占用了巨大资源(不一定是内存)且不是那么重要的进程来释放资源。

    • OOM发生时如果程序能正常处理这个异常情况,比如不再申请更多的内存或其它资源,或者放弃那个子任务或子线程,系统OOM状态是可以回到正常情况,事实上系统也期望你这么做。

12.JVM类加载机制别?自写java.lang.String能加载吗?

当自己定义了一个 String类 ,且包名也是java.lang,为什么不会被加载,因为双亲委派机制,当加载String类时,会一层一层的往上委托,直到在启动类加载器Bootstrap ClassLoader,而启动类加载器能够加载String类,因为在java包下有,所以加载的是Java中的String,而不是自定义的。

13.Thread Local底层原理?怎么避免内存泄漏

《提升能力,涨薪可待》-ThreadLocal的内存泄露的原因分析以及如何避免 - 掘金 (juejin.cn)

现在,我们可以看出ThreadLocal的设计思想了:

(1) ThreadLocal仅仅是个变量访问的入口;

(2) 每一个Thread对象都有一个ThreadLocalMap对象,这个ThreadLocalMap持有对象的引用;

(3) ThreadLocalMap以当前的threadLocal对象为key,以真正的存储对象为value。get()方法时通过threadLocal实例就可以找到绑定在当前线程上的副本对象。

ThreadLocal底层实现原理详解 - 掘金 (juejin.cn)

内存泄漏问题:--定时去remove操作!

key 使用强引用

当hreadLocalMap的key为强引用回收ThreadLocal时,因为ThreadLocalMap还持有ThreadLocal的强引用,如果没有手动删除,ThreadLocal不会被回收,导致Entry内存泄漏。

key 使用弱引用

当ThreadLocalMap的key为弱引用回收ThreadLocal时,由于ThreadLocalMap持有ThreadLocal的弱引用,即使没有手动删除,ThreadLocal也会被回收。当key为null,在下一次ThreadLocalMap调用set(),get(),remove()方法的时候会被清除value值。

15.synchronized和 Lock区别,实现原理?

还有很多口头说的问题,没有记录····

算法题:直接手撕一个大数相加的代码

总结:

问的其实比较常规,但是自己八股这一块背的还不行,基本的原理没有理解深入,或者深入透彻!

算法刷的远远不够···

项目自己一定好好深入理解每一部分原理,同时寻求新的好的项目!

美团---实习--【第三档】相关推荐

  1. 美团实习| 周记(五)

    本周知识清单如下:ps文末有惊喜链接↓↓↓ UI小课堂 TextView行间距.字间距 EditText有光标不弹出软键盘 EditText限定输入字符的类型.最大数量 指定Dialog宽高 资源文件 ...

  2. 美团实习面试:熟悉红黑树?能不能手写一下?

    点击关注公众号,Java干货及时送达  来源:https://zhenbianshu.github.io 图片 手写红黑树确实有点过分了,但我觉得写不出来也正常,只要理解就行 红黑树是数据结构中比较复 ...

  3. 美团实习面试经历--基础研发平台后台

    昨天去美团实习生面试的,岗位是基础研发平台后台开发.预约时间是下午五点,全程一二面一共大约80分钟.在这里首先我想对HR小姐姐(很温柔),一面哥(很帅),二面叔(很真实)说一声谢谢,你们态度很好,优秀 ...

  4. 美团实习面试:熟悉红黑树是吧?能不能写一下?

    点击关注公众号,Java干货及时送达 手写红黑树确实有点过分了,但我觉得写不出来也正常,只要理解就行 红黑树是数据结构中比较复杂的一种,最近与它交集颇多,于是花了一周的空闲时间跟它死磕,终于弄明白并实 ...

  5. 美团实习| 周记(三)

    本周知识清单如下,ps本周的感悟非常诚恳不容错过哦~ 颜色透明度计算 SpannableString类 快速切换到主线程更新UI的三种方法 RecycleView的item动画 使用Rxjava实现点 ...

  6. 美团、飞猪基础架构组实习经历分享

    一个朋友分享自己在飞猪和美团基础架构组实习的经历,很不错的分享,非常用心! 我个人觉得已经是很好的实习经历了,在飞猪的时候做业务,在美团的时候接触的是基础架构,这两方面一结合,不得直接起飞了啊,为以后 ...

  7. 美团点评暑期实习个人总结

    来美团实习两个多月了,在这段时间学习了很多东西,在这里做一个总结. 技术方面 刚开始几天阅读了公司常用的一些中间件,只是囫囵吞枣的看了看用途和应用场景,大部分的实现原理都没去深究,导致看一遍就忘了.这 ...

  8. 美团-测试开发工程师-18年暑期实习-一面二面

    美团实习 测试开发岗 两面技术+一面hr 一面 35min的面试时间,电话面试,按照简历的专业技术部分问的,先问项目性能指标,C++,再Linux常见命令,网路(我说我不是很熟),数据库.最后给了一个 ...

  9. 面经实习:美团测试开发 成都华为 软件开发

    面经:美团测试开发一面 华为 软件开发 HR说面试已过 博主是双非在校研二控制工程学生这篇文章用来记录我的面试经验,目前是自学Python.数据库.非科班. 美团 岗位:测试开发实习 笔试:3月中旬左 ...

最新文章

  1. 插入,冒泡,选择,快速排序,二分查找
  2. VS中使用NuGet安装依赖时提示:无法安装程序包“xxx”。你正在尝试将此程序包安装到目标为“.NETFramework,Version=v4.5”的项目中
  3. Visualization Document Feb 12 16:42
  4. mysql修改子分区_创建MySQL子分区方法
  5. WinForm 图片变灰方法
  6. 19. Rootkit detectors (隐形工具包检测器 5个)
  7. Python+Appium+夜神模拟器安装与简单运行(2/2)
  8. 玻璃质感_现代质感的顶层公寓,玻璃扶手让楼梯整个变透明!
  9. Python 实训3 简单的好友通讯录管理程序
  10. winrar3.80注册码
  11. 基于Python的视频解析器
  12. RGB颜色转16进制颜色
  13. google内部考核制度OKR
  14. superforming的sql-labs大通关之第一部分(第1~10关)解析及注入方法
  15. Windows桌面图标小工具:去除桌面图标小箭头|刷新图标缓存
  16. numpy向量化函数
  17. 中了一篇ccf的b类会议sdm'15,要去温哥华参会。很高兴啊!!!!
  18. Problem A: 薪酬计算
  19. 遍历列表的两种常见方式
  20. 物联网卡能否永久使用

热门文章

  1. linux python默认安装目录_怎么查看python的安装目录
  2. swiftUI-官方文档(to be continued)
  3. 分位数(quantile)
  4. 书单推荐|不惧复工,工作轻松
  5. 吴秀波负面缠身,中小企业员工面对负面只能坐以待毙?
  6. 把ChatGPT接入我的个人网站
  7. Unity-Wwise-Oculus踩坑笔记
  8. Skia深入分析10——Skia库的性能与优化潜力
  9. w 命令的解释与示例
  10. 有自觉php的吗 说说,关于人要懂得自觉的说说句子