1.介绍一下Collection集合类。
首先分成两个顶层接口,Collection接口和Map接口。
Collection接口往下大体上分为Set接口和List接口。
Set接口是集合,实现类有hashset,treeset。
List接口是列表,实现类有linkedlist,arraylist。
Map接口的实现类有hashmap,hashtable等等。
2.线程有哪些状态?如何转换?
线程有五个状态,分别是ready(代表就绪状态,就是刚new出来还没有start),runnable(线程执行状态),blocked(线程被阻塞状态,比如争抢锁失败),waiting(调用object.wait),time-waiting(调用Thread.sleep())
3.讲一下threadlocal。
threadlocal可以用于存放线程私有的数据。
每一个线程有一个threadlocalmap,threadlocalmap里key是指向某个threadlocal实例的弱引用,value代表的是threadlocal.set()存储的数据。如果不用这个数据了的时候没有通过remove方法而是设置threadlocal=null的话,GC时弱引用会被清理,所以通过threadlocal的弱引用没有办法访问到对应value了就会产生内存泄漏。
4.线程池拒绝策略有哪些?
1.abortpolicy:抛弃这个任务,报错。
2.discardpolicy:抛弃这个任务,不报错。
3.callerrunspolicy:调用创建线程的线程执行该任务。
4.discardoldestpolicy:丢弃队列中存在时间最长的任务取而代之。
5.假设用一个线程池写日志,那选择什么拒绝策略?
选择3.
6.讲一下缓存穿透、雪崩、击穿、以及解决方案。
缓存穿透:指的是大量访问一个缓存中不存在的key,因此请求会大量打到数据库中从而导致数据库宕机。
解决方案:布隆过滤器、缓存空对象。
缓存雪崩:指的是不停访问数据库中大量失效的热点key,因此请求会大量打到数据库中从而导致数据库宕机。
解决方案:在过期时间上加上一个随机值、限流算法
缓存击穿:指的是不停访问数据库中刚失效的一个热点key,因此请求会大量打到数据库中从而导致数据库宕机。
解决方案:使用锁机制解决(只允许一个线程重建缓存)、永不过期策略(逻辑上设置过期时间,实际上不设置过期时间,当发现超过逻辑过期时间后,会使用单独的线程去更新缓存,也要加锁)
7.说一下垃圾回收算法
垃圾回收算法有四种,复制算法、标记清除算法、标记压缩算法和分代垃圾回收算法。
复制算法指的是有两块一样的内存区域,一块充满对象,一块为空,将充满对象的一块区域中活的对象复制到另一块区域中,然后清除充满对象的那一块区域。特点:没有内存碎片,但是需要比较大的内存空间,因为你要进行复制操作,同时内存使用效率低,因为你只能在一半的内存区域创建对象。
标记清除算法指的是标记存活对象,然后直接清理不存活的对象。特点:存在内存碎片。
标记整理算法指的是标记存活对象,移动存活的对象到内存区域的一侧,然后清理不存活的对象。特点:没有内存碎片,但是速度慢。
分代垃圾回收算法指的是将堆内存分成年轻代(eden区、survivor from区和 survivor to区)和老年代后的young gc(清理eden和survivor区)和full gc(所有区域都清理)。具体过程如下:
新创建的对象都会放在eden区,如果对象过大就放入老年代。这些对象经过第一次Minor GC后,如果仍然存活,将会被移到Survivor from区。
对象每经历过一次young gc,年龄+1,当年龄到一定程度之后放入survivor from区,survivor from区满了会采用复制算法将存活对象复制到survivor to区。
当对象年龄到达15,转入老年代。
当老年代空间不足就会触发FULL GC。
8.I/O密集情况下怎么分配年轻代和老年代比例?
I/O密集型应用通常会频繁地创建和销毁对象,可能会导致年轻代较高的GC频率,所以需要确保有足够的年轻代空间来容纳这些短生命周期的对象,从而减少年轻代GC的频率和时间。所以可以增大年轻代的比例可以减少对象从年轻代晋升到老年代的频率,从而减少老年代GC的压力。
9.一次url过程。
将地址输入到浏览器中后:首先查询浏览器缓存,看看是否有ip地址,有了返回,没有就查询操作DNS系统缓存,有就返回,没有的话向本地DNS发起域名解析请求,本地DNS会向根域名服务器发起请求,根域名服务器返回对应的顶级域名服务器地址。
本地DNS服务器向顶级域名服务器发起解析请求,顶级域名服务器返回对应权威域名服务器地址。
本地DNS服务器向权威域名服务器发起解析请求,权威域名服务器返回最后的ip地址。
然后进行三次握手建立TCP连接,发起http请求,服务器返回数据。
10.什么隔离级别会出现幻读?
读未提交
11.myisam支持备份吗?
支持,使用mysqldump命令。
12.讲一下AOP?
AOP采用动态代理的方式插入逻辑,动态代理的方式有两种,
第一种是通过JDK动态代理实现:自定义类实现invocationhandler接口,重写invoke方法,可以在执行的前后插入逻辑。
第二种是通过CGLIB动态代理方式实现:底层采用ASM字节码生成框架,修改需要代理类的字节码文件,生成这个类的子类并重写类得所有课重写的方法,在重写的过程中写入额外的逻辑。
13.怎么写日志的AOP?
@Aspect @Component public class LoggingAspect { @Before("execution(* com.example.demo.service.*.*(..))") public void logBefore(JoinPoint joinPoint) { System.out.println("Executing method: " + joinPoint.getSignature().getName()); } @AfterReturning(pointcut = "execution(* com.example.demo.service.*.*(..))", returning = "result") public void logAfterReturning(JoinPoint joinPoint, Object result) { System.out.println("Method executed: " + joinPoint.getSignature().getName()); System.out.println("Return value: " + result); } }
springboot启动文件里里加上@EnableAspectJAutoProxy。