移动一面
1.Hashmap原理
-
Hashtable 是早期Java类库提供的一个哈希表实现,本身是同步的,不支持 null 键和值,由于同步导致的性能开销,所以已经很少被推荐使用。
-
HashMap与 HashTable主要区别在于 HashMap 不是同步的,支持 null 键和值等。通常情况下,HashMap 进行 put 或者 get 操作,可以达到常数时间的性能,所以它是绝大部分利用键值对存取场景的首选。
-
TreeMap 则是基于红黑树的一种提供顺序访问的 Map,和 HashMap 不同,它的 get、put、remove 之类操作都是 O(log(n))的时间复杂度,具体顺序可以由指定的 Comparator 来决定,或者根据键的自然顺序来判断。
2.hashmap数据插入规则
- 1.判断数组是否为空,为空进行初始化;
2.不为空,计算 k 的 hash 值,通过(n - 1) & hash计算应当存放在数组中的下标 index;
3.查看 table[index] 是否存在数据,没有数据就构造一个Node节点存放在 table[index] 中;
4.存在数据,说明发生了hash冲突(存在二个节点key的hash值一样), 继续判断key是否相等,相等,用新的value替换原数据(onlyIfAbsent为false);
5.如果不相等,判断当前节点类型是不是树型节点,如果是树型节点,创造树型节点插入红黑树中;(如果当前节点是树型节点证明当前已经是红黑树了)
6.如果不是树型节点,创建普通Node加入链表中;判断链表长度是否大于 8并且数组长度大于64, 大于的话链表转换为红黑树;
7.插入完成之后判断当前节点数是否大于阈值,如果大于开始扩容为原数组的二倍。
3.ConcurrentHashMap原理,为什么多线程条件下性能这么好
我从sync在1.6做的优化谈的,他从锁的粒度方面谈的
- JDK1.7版本: 容器中有多把锁,每一把锁锁一段数据,这样在多线程访问时不同段的数据时,就不会存在锁竞争了,这 样便可以有效地提高并发效率。这就是ConcurrentHashMap所采用的"分段锁"思想:ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment是一种可重入锁(ReentrantLock),在ConcurrentHashMap里扮演锁的角色;HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组。Segment的结构和HashMap类似,是一种数组和链表结构。一个Segment里包含一个HashEntry数组,每个Segment守护着一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得与它对应的Segment锁
- 1.8中放弃了
Segment
臃肿的设计,取而代之的是采用Node
+CAS
+Synchronized
来保证并发安全进行实现 - 对于锁的粒度调整为对每个Node元素进行加锁
- 然后是定位节点的hash算法被简化了,这样带来的弊端是Hash冲突会加剧。因此在链表节点数量大于8时,会将链表转化为红黑树进行存储。这样一来,查询的时间复杂度就会由原先的O(n)变为O(logN)
3.mysql优化
-
设计:存储引擎,字段类型,范式与逆范式
-
功能:索引,缓存,分区分表。
-
架构:主从复制,读写分离,负载均衡。
-
合理SQL:测试,经验。
- Innodb :数据完整性,并发性处理,擅长更新,删除。
myisam:高速查询及插入。擅长插入和查询。
3.a.微博主要是插入微博和查询微博列表,较为适合MyISAM;
a.财务系统除了读取和插入,经常要进行数据的修改和删除,较为适合InnoDB;
4.spring的aop怎么实现的
1.AOP(Aspect Orient Programming),我们一般称为面向方面(切面)编程,作为面向对象的一种补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理、日志、缓存等等。AOP实现的关键在于AOP框架自动创建的AOP代理,AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ;而动态代理则以Spring AOP为代表。本文会分别对AspectJ和Spring AOP的实现进行分析和介绍。
2.Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler
接口和Proxy
类。
如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final
,那么它是无法使用CGLIB做动态代理的。
5.Rabbitmq实现原理
-
原理
- 最核心的组件是 exchange交换机和quene消息队列 生产消息的把消息先发给交换机,同时会传递一个Rouing_key,交换机会根据这个key按照特定的路由算法,将消息给特定的queue.
- 和queue一样exchange也可以设置为持久化,临时或者自动删除
-
使用场景
- 在我们秒杀抢购商品的时候,系统会提醒我们稍等排队中,而不是页面卡死或报错给用户,现在的下单操作,不仅仅是一个简单的数据的库存的CRUD,可能还伴有积分的查询,比如京豆,优惠券、积分、下单成功反馈等等各种消息,像这种排队结算就用到了消息队列机制,数据排队一个一个处理,而不是大量同时处理把数据库压力过大导致宕机,所以RabbitMQ本质上起到的作用就是削峰填谷,为业务保驾护航
-
消息持久化:投递消息的时候durable设置为true
6.copyOnwriteArraylist实现原理
- COW通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。对CopyOnWrite容器进行并发的读的时候,不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,延时更新的策略是通过在写的时候针对的是不同的数据容器来实现的,放弃数据实时性达到数据的最终一致性。
- 实际上CopyOnWriteArrayList内部维护的就是一个数组,并且该数组引用是被volatile修饰,注意这里仅仅是修饰的是数组引用,其中另有玄机,稍后揭晓。关于volatile很重要的一条性质是它能够够保证可见性