那些年,面试的那些事儿

A:先问两个比较基础的吧,说说八大数据类型吧(先问两个最基本的,试试这货的水准,看看是不是个水货,这个都不知道的话,就直接滚蛋,免得浪费我时间)

B:(这..)

  •       浮点型:double、 float
  •       字符型:char
  •           整型:byte、 short、 int 、long
  • Boolean型:boolean

A:那什么是反射呢?

B:en~(果然够基础啊!)

对于任何一个类,都能知道他的属性与方法;对于任意一个对象,都能调用它的方法和属性。

A:嗯,那说说你用到过的集合,并简单阐述一下吧:

B:那我先说说List吧:

  • ArryList: 底层采用的是数组,查询快,增删慢。
  • LinkList: 底层采用的是链表,查询慢,增删快。
  •   Vector: 这个知道,底层同样采用的是数组,但是没怎么用过。

A:打断一下,为什么ArryList查询快,增删慢;而LinkList查询慢,增删快呢?(我倒要看看这货是不是又是一位八股文"大佬")

B:

        1.那我先说说这两个查询快慢的原因吧,因为Arrylist底层是数组,每次查询的时候我们通过下标进行查询,不需要去进行比较,查询方式是首地址+ (元素长度*下标) ,基于这个位置读取相应的字节就可以了;而LinkList底层是链表,我们每次去查询时,需要一个一个去比对,如果按1s查询一个的话,我们查询n个就需要ns,这样会耗费很长的时间,所以查询慢。

        2.接着我再说说两者增删快慢的原因吧,ArryList每次添加或删除数据时,我们如果想要插入数据,那么擦入数据之后的元素就会挨个往后移,删除则与之相反,还有就是如果内存不足的情况下,就需要扩容,这些都会导致增删慢,但是有种特殊情况是,如果你要插入的数据时在首位或者末位,这个时候速度会很快;而LinkedList底层是链表,例如我们现在想要添加一个元素在A和B之间,这两者之间会自动断开,把我们想要插入的数据放到这两个元素之间,删除同样与之相反。

A:嗯,接着往下说。(没想到这货还知道的这么详细)

B: 集合还有个Set:

  • HashSet:集合元素可以为空,不可重复,有序。

                底层采用的是链表 + 哈希表的算法,链表保证元素的添加顺序,哈希表表保证元

                素的唯一性。        

  • treeSet:有序,不可重复,底层采用的是红黑树算法,擅长于范围性查询。

A:Map有用过么?

B:有的,Map有:

  • HashMap:是一个线程不安全的map,方法中没有synchronized(初始大小为16,加载因子    0.75,扩容为1.5倍)
  • HashTable:方法中加入了synchronized 关键字,但是现在慢慢被ConcurrentHashMap慢慢   取代了。
  • ConcurrentHashMap:jdk1.8之后,采用了CAS和synchronized技术来保证线程安全,底层  采用的是:数组 + 链表 + 红黑树。 

A:你刚才有提到那个CAS和synchronized,你能详细说下你对他们的理解吗?

B:

CAS是基于锁的一种操作方式,是乐观锁…

A:那个再打断一下,你提到了锁,你可以详细说明一下吗?

B:

        总所周知,我们java中锁分为乐观锁和悲观锁,那我先说一下乐观锁,见名知意我们可以

清楚的知道,当我们在使用它的时候,它会乐观的认为我们不会去修改,就不会加锁,极

大的提高了效率,多用于读比较多的场景;悲观锁,这是一个满满负能量的锁,当我们去使

用它的时候,会认为我们会去修改它,然后就会加锁,性能就会降低,多用于写较多的场

景。

A:可以,那你再接着说说之前的问题。

B:

对了,我刚才说到那里来着了(叫你三番两次的打断我)

A:CAS!(这货在想啥啊,自己说的啥都不记得了)

B:哦哦,不好意思啊

常用的实现方式为:

        compare and swap《比较与交换》

 实现操作通常是由以下三个数来完成的:

        1. M 读取的变量值

        2. A 旧的预期值

        3. B 新的修改值

更新条件:

        当CAS进行修改操作的时候,当且仅当M=A,才会把M修改为B,否则什么都不做,我大          概知道这么多,具体原理需要去了解下CAS实现原理。

A:嗯,那有什么缺点吗?

B:

        这个是肯定的是会有的,鱼与熊掌是不可兼得的,因为提搞了性能,所以安全就会得不到保障,就出现了ABA问题。当CAS去修改数据时,M初始值读取的是A,准备修改的时候A=B,确实是满足了条件,但是这个A可能是个多变体,他首先变成了B,接着又变成A,这个时候问题就来了,也就是我上面的说的ABA问题。

A:嗯,那我们怎么去解决这个问题呢?

B:(咋的,这是要"夺命几连"问的节奏啊)

        这个嘛,当然是采用Version版本号来解决啦,当A每次变化时,就Version+ 1,这样B读取A的时候,同时把版本号一起读取,这样就算A再怎么变换身份,就会出现版本号不一致。

A:可以,那String、Stringbuilder、Stringbuffer的区别:

B:

  1. String是字符常量,创建后不可更改;后两者是字符变量,创建后可以更改。
  2. String和Stringbuilder线程是不安全的,而StringBuffer 线程是安全的

A:嗯,那“==” 与 “equals”的区别呢?

B: 

1.“equlas”是超类Object中的方法;“==”是操作符。

2. “==”一般多应用于数值间的比较;“equals”一般多用于对象之间的内存地址的比较。

3. “equlas”的运行速度没有“==”快。

A:上面这些都是些基础知识,接下来我再问问你些关于Redis方面的吧。(看来基础没什么问题了,那我再试试这货Redis掌握的怎么样)

B:好咧(咦,这个变态不知道又会问些什么问题~)

A:  嗯,那你先说说Redis数据类型以及它的使用场景。

B:

1.String(常规计数,例如微博的粉丝数量等),key=>value,value可以是string类型,也可以是数值类型。
2.List(关注列表,粉丝列表)
3.hash(用户信息、商品信息等),key=>value,
4.set(点赞、订阅等)
5.Zset(排行榜、用户列表)

        

A:那能列举一些你常用的一些命令吗?

B:    

  •         String类型:
Set age 24    赋值
Get age        取值
incr age       自增1
decr age       自减1
mget age age1    获取多个值
  •          list类型
lpush list1  num从列表list左边插入一个数据;
lpop list1  num 从列表list左边移除一个数据。
Rpush list1  num 从列表list右边插入一个数据;
Rpop list1  num从列表list右边移除一个数据。
llen list1  获取列表list的长度。
  •          hash类型:
hset  name tom 往hash里面添加key-value
hget  name 通过key向hash里面获取相应值
hmget name1 name2 通过key从hash里面获取所有Value
  •          set类型:
sadd  set1  num 向set1里添加数据
srem  set1  num 从set1里删除元素
scard  set1查看set1里面存在的个数
sismember set1 num 从set1查看是否存在某个数据
  •         Zset: 
Zadd student 1 tom 向学生表添加数据
Zrem student tom 从学生表里删除数据
Zrem student tom1 tom2 从学生表里删除多条数据
Zcard tom 查询数据
Zrange student 0 5 score根据学生表里的分数进行排序,排序区间是0,5区间
Zrevrange student 0 5 score 跟上面一样,这里是从大到小进行排序

             

A:嗯,什么是Redis持久化操作,提供了那两种持久化方式?

B:

        Redis持久化就是将缓存中的数据写入到本地磁盘中去,防止数据库宕机从而导致的数据丢失,这两种持久化方式分别是:

  •         AOF:

                1.write:根据条件,将aof_buf中的数据写入到aof文件中去

                2.save:根据条件,调用fsync、fdatasync 将aof文件写入到磁盘中去。

  •         RDB:

                1.RDBSave(生成RDB文件)

                2.RDBLoad(从文件加载内存)

  

A:那RDB与AOF的区别呢?    

B:区别的话:

  1. aof频率更新比rdb高,数据还原aof会优先
  2. RDB的效率优先于AOF

A:那它的储存结构呢?

B:

Redis通讯协议是通过resp的格式命令文本储存的

A:嗯,那再谈谈你对于缓存穿透、缓存击穿、缓存雪崩的理解吧

B:

  • 雪崩:

        由于原有缓存失效,新缓存又未到,在这期间原本应该请求缓存数据的请求现在直接请求了数据库,造成了数据的压力过大,从而导致了宕机

  • 缓存击穿:

        原本应该请求缓存中的key,这时候失效了,大批量的请求直接请求了数据库,造成了数据库的压力过大,从而导致了宕机。

  • 缓存穿透:

        用户要请求的数据,压根数据库就没有,自然缓存中也不会有,用户去缓存中查询数据,找不到对应Key的Value,然后又去数据库进行查询,依然查不到,返回了null,这两次查询都是毫无意义的。

A:说下你之前SpringCloud项目都有用到过那些组件吧

B: 

  •     注册中心: Eureka
  •     动态代理:Feign
  •     负载均衡:Ribbon
  •            网关:GetWary

A:那你们服务之间的调用采用的是什么?

B: 

        Feign,通过注解和选择的机器,拼接url路径,来发送请求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值