网易面试 备战-1

一面

1、HashMap和Hashtable的区别

HashMap 不是线程安全的,Hashtable是线程安全的; 使用了关键字synchronized进行同步; 在jdk1.5开始 有了CurrentHashMap 来替代Hashtable。  CurrentHashMap 性能比 Hashtable 要好,使用了 锁分段 技术,jdk1.8开始使用CAS算法实现。

HashMap 有个加载因子,默认0.75,当桶被填满3/4时,需要rehash,扩展桶的大小。

如果碰到了 hash冲突, 会通过链表来解决这个问题。

HashMap的底层数据结构 是一个Entry<K,V>对象的数据,数据的下标索引 是通过 hash 值与 length-1 (容器长度-1)进行取模(%)运算 得到的。源码中使用的是  indexFor() 方法进行的 按位与(&)运算,而非取模运算(因为二进制运算效率更高,但是代码可读性 大大降低)。

当HashMap的某个索引的冲突值 达到8个以及以上时,会将链表升级成 红黑树(只关心二叉查找树的查找,不关心红黑树的构造以及左旋和右旋,有点复杂 网址: http://www.cnblogs.com/mfrank/p/9227097.html

红黑树网址:https://www.cnblogs.com/skywang12345/p/3245399.html#a2)。

 

CurrentHashMap: 

 锁分段 技术(1.8之前):https://blog.csdn.net/bigtree_3721/article/details/76407543

锁分段技术的segment希望数据均匀的分布在每个段落中,所以与key的hash 取余得到key在entry数组中的位置 不一样,

锁分段技术是将 key的hash值 取最高的4位 与 (数组长度-1) 取余; 如果用低的四位的话,会出现有些分段数据量大,有些分段数据量小,不均匀的情况。

 

CAS实现(1.8版本):https://blog.csdn.net/u010723709/article/details/48007881

 

2、HashMap的数据结构,为什么新添加的节点要添加到链表头部?

void addEntry(int hash, K key, V value, int bucketIndex) {  
    Entry<K,V> e = table[bucketIndex];  
    table[bucketIndex] = new Entry<K,V>(hash, key, value, e);  
    if (size++ >= threshold)  
        resize(2 * table.length);  
bsp;  

bucketIndex是数组的索引位置,如果此索引位置没有entry对象,就没有链表;数组的该位置只有当前值。

如果此索引位置有entry对象,那么 table[bucketIndex] = new Entry<K,V>(hash, key, value, e);  中的 new Entry 就是新的链表的表头,指向的next 就是老的存在hash冲突的key 对应的值。(这个是单向链表)。

见文章: https://www.cnblogs.com/peizhe123/p/5790252.html

 

3、ConcurrentHashMap支持高并发的原理,段锁为什么要采用重入锁而不是synchronized?

重入锁等待可中断,可使用公平锁和非公平锁,锁可以绑定多个条件(可以根据condition状态(await, signal) 来唤醒指定的线程)。

 

4、讲一讲AtomicInteger,为什么要用CAS而不是synchronized?

CAS是一个乐观锁,性能高, 基于unsafe的比较方法,联合volatile 实现线程安全。

 

5、线程池的工作原理,几个重要参数,然后给了具体几个参数分析线程池会怎么做,最后问阻塞队列的作用是什么?

先使用核心线程处理,满了再放入队列; 队列满了,再创建普通线程,直到达到最大的线程数。此时再进来请求,则根据饱和策略处理(默认直接抛出异常)。

线程池的几个重要参数: 核心线程数,最大线程数,队列长度, keepAlive存活时间(活跃线程超过核心线程时,多余的线程的最大存活时间),线程的异常处理。

阻塞队列的作用: 缓冲,避免创建普通线程 带来系统开销。

参考网址:https://www.cnblogs.com/dongguacai/p/6030187.html

 

6、JMM如何保证内存可见性,Happens-before

https://blog.csdn.net/bryce123phy/article/details/52260168  todo

volatile关键字:

1、当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存;

2、当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量;

 

7、Java运行时数据区域画出来,如果有一个对象有一个域是String s = “abc”;,这个s在哪里,“abc”在哪里

s 在虚拟机栈中,存在String对象abc的地址, abc作为一个对象实例,存储在 Java堆上。

 

二面

1、项目介绍,把项目的角色和用户的表结构画出来,这个表设计符合几范式?让你来改进这个表设计,你会怎么改?

一般表 需要满足第三范式:第一范式:每列不可拆分;第二范式:有主键;第三范式:数据没有冗余。

 

2、Java反射熟悉吗?如何访问一个类的私有成员?私有函数呢?

java反射类:Class ct = Class.forName("reflectTest.ReflectTest");

				//访问类名
				ct.getName();
       //访问构造函数
        ct.getConstructors();
				访问方法
        ct.getMethods();
				//访问字段(成员变量)
        ct.getFields();

访问 一个类的私有成员,私有函数 可以使用

Method[] declaredMethods = ct.getDeclaredMethods();
        Field[] declaredFields = ct.getDeclaredFields();

3、为什么会出现死锁?你来写一个死锁,如何改一改这个代码避免死锁?(我把synchronized改成重入锁的tryLock)

死锁产生的原因:

1.因竞争资源发生死锁

2.进程推进顺序不当发生死锁

手写死锁代码: 写一下 可重入锁 以及避免死锁的方式。 todo

 

4、场景设计题,据说是考拉真实场景:

(1)查询某个用户收藏了哪些商品;

(2)查询某个商品被哪些用户收藏了;

(3)查询某个商品被收藏的次数;

设计了四个表,用户表、商品表、收藏表和商品收藏次数表;

如果一个用户快速点击收藏按钮怎么做?

怎么在高并发下保证性能?

怎么保证数据的一致性?等等各种问题。

最后这个问题, 太笼统,不管了。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值