小米一面
1 集合类图
2 .class文件魔数、版本
java编译生成固定格式的字节码(.class文件)供JVM使用,是因为字节码文件由十六进制值组成,而JVM以两个十六进制值为一组,即以字节为单位进行读取
魔数的固定值为:0xCAFEBABE(咖啡宝贝),魔数之后的4个字节为 次版本号与主版本号 例子(“00 00 00 34”) 转化为十进制为52,对应的主版本号为1.8
3 查看jvm进程内的线程状态
- 查看java的pid:
ps –ef|grep java
- 查看进程的所有线程的资源消耗情况
top -H -p pid
- 找到CPU负载高的线程pid, 把这个数字转换成16进制,(10进制转16进制,用linux命令: printf %x pid)。
- 用jstack dump 线程的信息
jstack 6396 >6396.dump
- 用vim,搜索“16进制pid”,就是搜一下16进制显示的线程id。搜到后,下面的堆栈就是这个线程打出来的
4 jdk1.8.0_161\bin目录下的工具
jconsole
- 一个java GUI监视工具,可以以图表化的形式显示各种数据。并可通过远程连接监视远程的服务器VM。
jstack
- Java堆栈跟踪工具,主要用于打印指定Java进程、核心文件或远程调试服务器的Java线程的堆栈跟踪信息。
jmap
- Java内存映射工具(Java Memory Map),主要用于打印指定Java进程、核心文件或远程调试服务器的共享对象内存映射或堆内存细节。
jstat
- JVM统计监测工具(JVM Statistics Monitoring Tool),主要用于监测并显示JVM的性能统计信息,包括gc统计信息。
jvisualvm
1.6,1.7,1.8自带,能够监控线程,内存情况,查看方法的CPU时间和内存中的对 象,已被GC的对象,反向查看分配的堆栈(如100个String对象分别由哪几个对象分配出来的).
…
5 synchronized锁原理、重入锁
线程状态,java.lang.Thread.State枚举表示,为什么将ready和running合并为runnable
1、NEW
(新建)2、RUNNABLE
(可运行)3、BLOCKED
(阻塞)4、WAITING
(无限期等待)5、TIMED_WAITING
(限期等待)6、TERMINATED
(结束)
javadoc 中说
处于 runnable 状态下的线程正在 Java 虚拟机中执行,但它可能正在等待来自于操作系统的其它资源,比如处理器。
当线程调用阻塞式 API,线程进入休眠状态,这里指的是操作系统层面的。从 JVM 层面,Java 线程状态依然处于 RUNNABLE 状态。JVM 并不关心操作系统线程实际状态。从 JVM 看来等待 CPU 使用权(操作系统线程状态为可运行状态)与等待 I/O (操作系统线程状态处于休眠状态)没有区别,都是在等待某种资源,所以都归入 RUNNABLE 状态。
6 HashMap&ConcurrentHashMap
7 hashCode、equals
1.equal()相等的两个对象他们的hashCode()肯定相等,也就是用equal()对比是绝对可靠的。
2.hashCode()相等的两个对象他们的equal()不一定相等,也就是hashCode()不是绝对可靠的。(生成hash值得公式可能存在的问题))
8 线程池,线程内部抛异常会不会影响其他线程,怎么回收不活跃的线程
在线程池中,一个线程出现问题不会导致其他线程的正常执行。会调用ThreadPoolExecutor.runWorker()
方法最后面的finally中的processWorkerExit()
,会将此线程remove,并重新addworker()
一个线程
- 参数
allowCoreThreadTimeOut
为true - 该线程在
keepAliveTime
时间内获取不到任务,即空闲这么长时间 - 当前线程池大小 > 核心线程池大小
corePoolSize
。
或者 executor.shutdown();
9 mysql隔离级别、脏读、不可重复读、幻读(删除数据算不算幻读),可重复读RR 怎么解决幻读
点击查看 ,在 InnoDB 下
在快照读读情况下,mysql通过mvcc来避免幻读。
select * from t where a=1;属于快照读
在当前读读情况下,mysql通过next-key来避免幻读。
select * from t for update (lock in share mode);属于当前读
索引类型,BTree和hash的特点
一:B-tree索引 相当于金字塔大树分支 例如1000条数据 也就10多行 那么查询也只需要10多次。独立索引只能用一个。
二:hash索引 一对一主键 不利于范围查询 无法利用前缀查询
10 mysql主从不一致解决方案
- 检测不一致原因,是否因为跨机房binlog网络延迟,
- 配置不一致,
max_allowed_packet
设置不一致,同步参数 未设置sync_binlog=1
或者innodb_flush_log_at_trx_commit=1
,mysql版本不一致, - …查看
11 spring+mybatis多数据源
12 递增有序数组,计算哪些位置的和为100
小米二面
13 redis分布式session
14 redis分布式锁
15 xxl-job分布式定时任务原理
16 dubbo使用zookeeper分布式协调
17 mysql大字符串建立索引
18 主键索引与非主键索引区别
19 AQS原理
前端有没有做过
20 算法题,2 3 3 3 5 9 一些数据,找出出现次数大于等于n/2的数
如果那个数字的出现次数大于等于数组长度的一半,那么你把这个数组排序,中间的数就是我们要找的数。
小米四面
21 redis主从架构
22 redis数据类型
23 10W QPS系统架构
- nginx负载均衡+lua 限流+redis
- java程序 并发+redis+ MQ+rpc
- 数据库分库分表,读写分离+高可用
24 ORM框架原理
通过解析数据库配置文件获取数据库连接信息并建立连接,通过解析映射文件可以获取映射类名、属性名、表名以及字段名等信息,得到名字后通过反射机制可以得到映射类信息,调用构造方法创建对象,调用每个属性的set方法给对象设值完成数据的装载
25 mybatis优缺点
MyBatis是嘴加单的持久层框架,小巧并且简单易学。
提供映射标签,支持对象与数据库的ORM字段关系映射
提供对象关系映射标签,支持对象关系组建维护
提供xml标签,支持编写动态sql。
SQL语句的编写工作量较大,尤其是字段多、关联表多时,更是如此,
对开发人员编写SQL语句的功底有一定要求
SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
编写动态sql时,不方便调试,尤其逻辑复杂时。
26 索引类型,各种类型特点
27 索引怎么加速查询
跟谁学一面
27 zookeeper zab协议
ZooKeeper 的核心是原子广播,这个机制保证了各个 Server 之间的同步。实现这个机制的协议叫做 Zab 协议。Zab 协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步):
选主:当服务启动或者 Leader 崩溃后,Zab 就进入了恢复模式,当新的 Leader 被选举出来,且大多数 Server 完成了和 Leader 的状态同步以后,恢复模式就结束了。
同步:状态同步保证了 Leader 和 Server 具有相同的系统状态。
Zab 协议的特性:
1)Zab 协议需要确保那些已经在 Leader 服务器上提交(Commit)的事务最终被所有的服务器提交。
2)Zab 协议需要确保丢弃那些只在 Leader 上被提出而没有被提交的事务。
27 redis string数据类型实现方式
SDS(simple dynamic string,简单动态字符串)
- SDS中,有专门用于保存字符串长度的变量
- 防止缓冲区溢出.当我们需要对一个SDS 进行修改的时候,redis 会在执行拼接操作之前,预先检查给定SDS 空间是否足够(free记录了剩余可用的数据长度),如果不够,会先拓展SDS 的空间,然后再执行拼接操作。
- 减少扩展或收缩字符串带来的内存重分配次数,预分配策略
- 二进制安全,通过len这个属性判断字符串的结束
28 mybatis一、二级缓存
1、MyBatis一级缓存的生命周期和SqlSession一致。
2、MyBatis一级缓存内部设计简单,只是一个没有容量限定的HashMap,在缓存的功能性上有所欠缺。
3、MyBatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为Statement。
1、MyBatis的二级缓存相对于一级缓存来说,实现了SqlSession之间缓存数据的共享,同时粒度更加的细,能够到namespace级别,通过Cache接口实现类不同的组合,对Cache的可控性也更强。
2、MyBatis在多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用二级缓存的条件比较苛刻。
3、在分布式环境下,由于默认的MyBatis Cache实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将MyBatis的Cache接口实现,有一定的开发成本,直接使用Redis、Memcached等分布式缓存可能成本更低,安全性也更高。
纸币面额有 1, 2, 5, 10, 20, 50, 100,假设有一个自动售货机需要给用户找零 x 元,请打印出所有可能的找零组合。(leetcode 518. 零钱兑换 II)
动态规划
class Solution {
public int coinChange(int[] coins, int amount) {
// 0.因为凑成amount金额的硬币数最多只可能等于amount(全用 1 元面值的硬币),
// 所以初始化为amount + 1就相当于初始化为正无穷,便于后续取最小值;
int max = amount + 1;
// 1.dp[i] = x表示,当目标金额为i时,至少需要x枚硬币
int[] amounts = new int[amount + 1];
Arrays.fill(amounts, max);
// 2.这里很明显在目标金额为0的情况下, 需要0枚硬币即可;
amounts[0] = 0;
// 3.然后从底部向上, 也即为从目标金额为: "1"开始至"amount"来推目标状态值
for (int i = 1; i <= amount; i++) {
// 3.1 对于每一个金额amount, 枚举所有的硬币面值
for (int j = 0; j < coins.length; j++) {
// 对于不符合条件的直接剪枝;
if (i >= coins[j]) {
// 3.2 利用上面推到出来的动态规划状态转移方程;
amounts[i] = Math.min(amounts[i], amounts[i - coins[j]] + 1);
}
}
}
return amounts[amount] > amount ? -1 : amounts[amount];
}
}
跟谁学二面
29 DDD领域驱动设计
30 业界链路压测
31限流算法
- 固定窗口计数器;
- 滑动窗口计数器;
- 漏桶;
- 令牌桶。
32 创建线程的方式
/*
corePoolSize : 线程池核心池的大小。
maximumPoolSize : 线程池的最大线程数。
keepAliveTime : 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
unit : keepAliveTime 的时间单位。
workQueue : 用来储存等待执行任务的队列。
threadFactory : 线程工厂。
handler 拒绝策略。
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
/*
阻塞队列:
ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。
LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列。
PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。
DelayQueue: 一个使用优先级队列实现的无界阻塞队列。
SynchronousQueue: 一个不存储元素的阻塞队列。
LinkedTransferQueue: 一个由链表结构组成的无界阻塞队列。
LinkedBlockingDeque: 一个由链表结构组成的双向阻塞队列。
拒绝策略:
ThreadPoolExecutor.AbortPolicy: 丢弃任务并抛出RejectedExecutionException异常。 (默认)
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务。(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务。
*/
26 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
青蛙简单跳台阶和变态跳台阶
/**
* 到达第 i 阶的方法总数 = 第 i -1 阶方法数 + 第 i -2 阶方法数 ,动态规划
*/
public int climbStairs3(int n) {
if ( n == 1) {
return 1;
}
int[] dp = new int[n + 1];
dp[1] = 1;
dp[2] = 2;
for (int i = 3; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i -2];
}
return dp[n];