一面(技术面)
一、Java内存模型:虚拟机栈-独享的(一个线程一个栈)、堆-共享的(新生代-复制算法、老年代-标记整理-清除)、程序计数器-独享的(CPU切换线程管理)、元数据区-共享的(类信息、常量、静态变量、方法)、本地方法栈-独享(和操作系统交互)
二、full gc怎么触发:新生代满minor gc;1、老生代满2、永久代满 3、minor gc 不了的晋升到老生代的数据大于老生代大小;4、选择了CMS GC算法导致;
三、gc算法:1、可达性2、引用计数法3、复制(内存分2份,左满移右) 4、标记整理-清除(所有对象标记生死状态,整理是死的归类到一起清除,清除是直接清除死标记)
四、高吞吐量的话用哪种gc算法:复制和标记整理-清除
五、ConcurrentHashMap和HashMap:node数组+链表>8升级红黑树;Synch锁二叉树首节点(hash不重复)+cas比较替换+分段锁来保证并发安全;
六、JDK8的stream的操作:reduce,max,min运算,flatMap合并流,filter过滤,map转大写,collect的json转数组;
七、volatile原理volatile的底层如何实现,怎么就能保住可见性了?1、对volatile修饰的变量,执行写操作的话,JVM会发送一条lock前缀指令给CPU,CPU在计算完成后会立即将这个值写回主内存,同时因为有MESI缓存一致性协议,所以各个CPU都会对总线进行嗅探,自己本地缓存中的数据是否被别人修改。
如果发现别人修改了某个缓存的数据,那么CPU会将自己本地缓存的数据过期掉,然后这个CPU上执行的线程在读取那个变量的时候,就会从主内存中重新加载最新的数据。2、禁止指令重排
八、线程池原理,拒绝策略,核心线程数:线程放到阻塞队列,处理中阻塞处理完唤醒;
九、1亿个手机号码,判断重复:1、hash(num)%1000 2、100个文件 3、每个文件读到hashmap.containsKey() 是否存在4、mysql.flink里 ,分组by phone ,distinct
十、单元测试介绍一下,多模块依赖怎么单元测试。Mockito
十一、线程之间的交互方式有哪些?保持线程顺序:
- Lock.wait() +lock. notify() synchronized(lock) run
- a.await() + b.signal() ( ReentrantLock condition a,b 条件锁)
- join方式 new TaskB(taskA.join);
二面(技术面)
一、限流算法:1、计数法 2、令牌桶 3、漏桶法
二、zk挂了怎么办:日志和数据满了;高可用是zab广播选主节点;分成三种角色:leader、follower和observer。leader负责写、follower和observer负责读。redis主从复制模型中,master挂掉之后是靠sentinel自动完成故障转移的
三、秒杀场景设计,应付突