记在前面
java基础
集合
开发中Java用得比较多的数据结构(集合)有哪些?
ArrayList 如何动态扩容的?Arraylist与LinkedList异同?
ArrayList是线程安全的吗?
不安全 原因是add方法 elementData[size++] = e;不是原子操作,当多线程添加的情况下,假如size=0时,添加第一个元素的线程添加成功,同时在size没有及时写到内存中时,这时另一个线程继续添加就覆盖了原来的值。要保证线程安全,可以如下使用: Collections.synchronizedList(new ArrayList<>()); 本质是给ArrayList的每个方法加synchronized关键字,本质是利用Object来上锁。
ArrayList是线程安全的吗?
循环删除list中元素会如下写会发生什么?
1
2
3
4
5
6
7
8
9
10
11
12
13
14// 会抛出 java.util.ConcurrentModificationException异常
for (String str : list) {
if ("a".equals(str)) {
list.remove(str);
}
}
// 正确移除元素
Iterator<String> it = list.iterator();
while(it.hasNext()) {
String str = it.next();
if ("a".equals(str)) {
it.remove();
}
}谈谈你对HashMap的理解,底层原理的基本实现,hashmap实现原理 put的过程?HashMap怎么解决碰撞问题的?
HashMap的遍历有哪两种常用的方法?或者HashMap的操作中,直接使用keySet()遍历有什么问题?
map.keySet()和map.entrySet()来进行遍历。keySet 先遍历iterator对象,后面再多一步操作hashmap.get(), 第二次遍历只是针对一个bucket的遍历,在hash碰撞不多的情况下性能并不会有大影响。
假如你回答HashMap是线程安全的,接着问有没有线程安全的map,接下来问conurren包?
线程池
- 平时线程池用的多么?看你项目中有用,讲讲线程池的实现原理。最好用笔简单画下。
- 线程池中的corePoolSize和maximumPoolSize有什么不同?
- 哪种场景下线程池用完后极速回收?
并发
synchronized和锁的区别,什么情况下使用synchronized和ReentrantLock?
java并发这块了解的怎么样?说说你对volatile关键字的理解?能保证原子性吗?
什么是Callable和Future?
Callable接口类似于Runnable,从名字就可以看出来了,但是Runnable不会返回结果,并且无法抛出返回结果的异常,而Callable功能更强大一些,被线程执行后,可以返回值,这个返回值可以被Future拿到,也就是说,Future可以拿到异步执行任务的返回值。可以认为是带有回调的Runnable。
Callable接口代表一段可以调用并返回结果的代码;Future接口表示异步任务,是还没有完成的任务给出的未来结果。所以说Callable用于产生结果,Future用于获取结果。
反射
反射讲一讲,主要是概念, 都在哪需要反射机制?
对于任意一个类,都能够知道这个类的所有属性和方法(成员变量和函数);对于任意一个对象,都能够调用它的任意一个方法和属性。
编译时刻加载类是静态加载类
运行时刻加载类是动态加载类
new 创建对象 是静态加载类,在编译时刻就需要加载 所有可能使用到的类动态加载类,在运行时加载功能性的类设计时 动态加载Class c = Class.forName(args[0]) ;反射的操作都是编译之后的操作,编译之后集合是去泛型化的。java中集合的泛型,是防止错误输入的,只在编译阶段有效,绕过编译就无效了。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// Foo的实例对象如何表示
Foo foo1 = new Foo();
// Foo这个类 也是一个实例对象,Class类的实例对象,如何表示呢
// 任何一个类都是Class的实例对象,这个实例对象有三种表示方式
// 第一种表示方式--->实际在告诉我们任何一个类都有一个隐含的静态成员变量class
Class c1 = Foo.class;
// 第二中表达方式 已经知道该类的对象通过getClass方法
Class c2 = foo1.getClass();
/*官网 c1 ,c2 表示了Foo类的类类型(class type)
* 万事万物皆对象,
* 类也是对象,是Class类的实例对象
* 这个对象我们称为该类的类类型
*/
// 不管c1 or c2都代表了Foo类的类类型,一个类只可能是Class类的一个实例对象
// 第三种表达方式
Class c3 = Class.forName("com.imooc.reflect.Foo");
// 我们完全可以通过类的类类型创建该类的对象实例---->通过c1 or c2 or c3创建Foo的实例对象
// 需要有无参数的构造方法
Foo foo = (Foo)c1.newInstance();反射的性能,如何优化?
- 由于JDK的安全检查耗时较多所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的 性能有了20倍的提升;
- 缓存大法 多次动态创建一个类的实例的时候,有缓存的写法会比没有缓存要快很多。
设计模式
能否手写个单例模式的?
装饰者模式
框架
spring
spring ioc aop 说下原理,理解,aop jdk 和cglib区别,spring选择什么,spring ioc用了什么模式,带来了什么效果?
spring有几种注入方式?
三种注入方式,构造器、接口、set注入,我们常用的是set注入。
springboot
项目中有用springboot,为什么用用springboot?
- 上手容易
- 独立运行
- 简化配置
- 自动配置
- 应用监控
springboot 的配置文件有哪几种格式?它们有什么区别?
.properties 和 .yml,它们的区别主要是书写格式不同。
springboot 的核心注解是哪个?它主要由哪几个注解组成的?
核心注解:@SpringBootApplication ,由三个注解组合而成
- @SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。
- @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项。
- @ComponentScan:Spring组件扫描。
springboot 自动配置原理是什么?
springboot可以兼容老 Spring 项目吗,如何做?
可以兼容,使用 @ImportResource 注解导入老 Spring 项目配置文件。
springmvc
- springmvc原理,流程?
mybatis
#{}和${}的区别是什么?
#{}是预编译处理,${}是字符串替换。Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值。Mybatis在处理${}时,就是把${}替换成变量的值。使用#{}可以有效的防止SQL注入,提高系统安全性。
mybatis提供了哪些动态sql标签?
mybatis提供了9种动态sql标签:trim | where | set | foreach | if | choose | when | otherwise | bind。
JVM
参数设置
- -Xms 堆的最小值
- -Xmx 堆的最大值
- -Xmn 新生代容量
- -Xss 设置栈容量
- -XX:PermSize -XXMaxPermSize 限制方法区的大小
- -XX:MaxTenuringThreshold 动态对象年龄判断
- -XX:SurviorRatio Eden与Survivor区的比例
- -XX:PretenureSizeThreshold 晋升老年代对象年龄
垃圾收集算法有哪些?
- 标记-清除算法:最基础的收集算法,分为两个阶段 标记和清除 ( 缺点 效率不高,标记和清除两个过程效率都不高; 空间问题 内存产生大量不连续的内存碎片,导致大对象无法找到足够连续的内存而不得不出发另一次垃圾收集)
- 复制算法:解决效率问题 将内存划分为大小相等的两块,每次只使用其中的一块,当这一块的内存用完了,就将还存活的对象复制到另一块上面,然后将已使用过的内存空间一次清理掉。 代价是将内存缩小了一倍。新生代98%是朝生夕死的,内存分为一块较大的Eden 空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor,回收时,将Eden和Survivor中还存活的对象一次复制到另一块Survivor空间上,最后清理掉Eden和刚用过的Survivor空间。Hotspot默认Eden和Survivor的大小比例是8:1
- 标记-整理算法:复制算法在对象存活率较高时就要进行复制操作,效率将会遍低。更关键的是不想浪费空间就需要额外空间进行担保,以应对内存中所有对象都100%存活的极端情况。根据老年代的特定标记过程一样,后续操作是让所有存活的对象都向一边移动,然后直接清理掉端边界以外的内存。
对象的内存布局 由几部分构成?
对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。
对象已死吗?如何判断? GC Roots 有哪些?
用到了什么 可达性分析算法 (Reachability Analysiss)
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI(Native方法)引用的对象
JVM中,如果把堆内存参数配置的超过了本地内存,会怎么样?
应用运行不了。
windows下:
1
2Error occurred during initialization of VM
Could not reserve enough space for object heaplinux下:
1
2error='Cannot allocate memory'
hs_err_pid1288.log
类加载器
双亲委派模型的工作过程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。
好处:就是Java类随着它的类加载器一起具备了一种带有优先级的层次关系 。Object类在程序的各种类加载器环境中都是同一个类。反之,不使用,Java类型体系中最基础的行为也就无法保证,应用程序也将会变得一片混乱
什么时候触发minor GC 什么时候触发full GC?
从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC;
对老年代GC称为Major GC;
而Full GC是对整个堆来说的;
Minor GC触发条件:当Eden区满时,触发Minor GC。
Full GC触发条件:
- System.gc()方法的调用
- 老年代空间不足
- 方法区空间不足
- 通过Minor GC后进入老年代的平均大小大于老年代的可用内存
- 由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小
redis
看项目中用过redis。redis有什么数据类型?
主要由五种:String、Hash、List、Set和Sorted Set
看项目中用过redis,用作缓存,哪种场景下适合用缓存?缓存击穿?
知道redis的持久化吗?都有什么缺点和有点?具体底层实现呢?
RDB快照和AOF日志
- RDB:Redis借助了fork命令的copy on write机制 在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件缺点:rdb有他的不足,就是一旦数据库出现问题,那么我们的RDB文件中保存的数据并不是全新的,从上次RDB文件生成到Redis停机这段时间的数据全部丢掉了。
- AOF:AOF日志的全称是append only file,它是一个追加写入的日志文件 对于那些无法忍数据丢失的应用,建议使用AOF日志。
redis过期策略都有哪些?LRU?写一个java版本的代码吧?
惰性删除 + 定期删除
被动删除:当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key
主动删除:由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期主动淘汰一批已过期的key。当前已用内存超过maxmemory限定时,触发主动清理策略。
当Redis内存使用达到maxmemory时,需要选择设置好的maxmemory-policy进行对老数据的置换
noeviction: 不进行置换,表示即使内存达到上限也不进行置换,所有能引起内存增加的命令都会返回error
allkeys-lru: 优先删除掉最近最不经常使用的key,用以保存新数据
volatile-lru: 只从设置失效(expire set)的key中选择最近最不经常使用的key进行删除,用以保存新数据
allkeys-random: 随机从all-keys中选择一些key进行删除,用以保存新数据
volatile-random: 只从设置失效(expire set)的key中,选择一些key进行删除,用以保存新数据
volatile-ttl: 只从设置失效(expire set)的key中,选出存活时间(TTL)最短的key进行删除,用以保存新数据
1
2
3
4
5
6
7
8public LRULinkedHashMap(int maxCapacity) {
super(maxCapacity, DEFAULT_LOAD_FACTOR, true);
this.maxCapacity = maxCapacity;
}
protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
return size() > maxCapacity;
}
使用redis如何设计分布式锁?使用zk可以吗?如何实现?这两种哪个效率高?
redis锁定的原理是利用setnx命令,即只有在某个key不存在情况才能set成功该key。这样就达到了多个进程并发去set同一个key,只有一个进程能set成功。
zookeeper实现了类似paxos协议,是一个拥有多个节点分布式协调服务?
zookeeper实现锁的方式是客户端一起竞争写某条数据,比如/path/lock,只有第一个客户端能写入成功,其他的客户端都会写入失败。写入成功的客户端就获得了锁,写入失败的客户端,注册watch事件,等待锁的释放,从而继续竞争该锁。
数据库
数据库索引问题,就是最左前缀问题 联合索引 (A.B),查询时where B = 会走索引吗,where A = 会走吗?
最左前缀匹配问题。
创建复合索引时应该将最常用作限制条件的列放在最左边,依次递减。不要过度索引
sql优化有哪些思路?
应尽量避免全表扫描,首先应考虑在 where 及 order by ,group by 涉及的列上建立索引。最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配
设计高并发系统数据库层面该怎么设计?数据库锁有哪些类型?如何实现?
数据库服务器采用集群方式部署。
数据库层面,主要就是用到垂直分库,水平分库, 读写分离,热备份等技术,提高数据库的读写能力
数据库锁?
悲观锁 for update
乐观锁 版本号 CAS
数据库事务有哪些?
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性
- 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
- 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
- 隔离性(Isolation):一个事务的执行不能被其他事务干扰。
- 持久性(Durability):一个事务一旦提交,他对数据库的修改应该永久保存在数据库中
为什么要分库分表?
性能问题,索引问题等
分库分表方案应该尽量避免的两个问题?
数据迁移 热点
如何设计可以动态扩容缩容的分库分表方案?
网络
cookie与session区别 ?
post与get区别 ?
一个网址url从浏览器中输入后发生了什么?
客观
- 客观印象最深的bug是什么?如何解决的?如何防止?
- 如何学习一个新技术,团队需要有人来学习,有没有自己的方法论?