美文网首页
【JAVA】面试题整理

【JAVA】面试题整理

作者: Y了个J | 来源:发表于2021-01-27 23:32 被阅读0次

压缩20M文件从30秒到1秒的优化过程
两个案例,从根上理解JVM字节码执行
Tomcat深入理解
jstat命令查看jvm的GC情况
对象头
Redis为什么变慢了?一文讲透如何排查Redis性能问题
天猫二面:内存耗尽后Redis会发生什么?
Nginx面试三连问
类加载器与类的加载过程
DB主从一致性架构优化4种方法
缓存与数据库一致性系列

设计个抢红包算法
设计个秒杀系统
设计个打卡签到业务
如何保证数据库主从延迟问题

我们更新了主库后,立即去读从库可能没那么及时读到最新数据,可以这么解决:
缓存标记法,并设置失效时间,时间大概就是我们主从同步延迟的时间,然后有标记就读主库,没标记后可以再去读从库,写库前先设缓存标记,没设成功就放弃这次修改,相当于设置一个主从开关。

如何保证redis和数据库一致性

一般是写完数据库后去删除redis缓存,但是可能出现写数据库成功,但是删redis缓存失败,导致缓存里还是旧数据,这种情况可以把redis有效期设短一点,等缓存失效后就会去数据库加载新的数据到缓存了。

加标识key,标记当前正在执行写请求,直接去读mysql,写请求最好能串行化。

大量并发写的情况下可以通过解析binlog来使缓存失效。

可以加锁写,写的时候其他读写请求阻塞等待,防止并发导致旧数据又覆盖了新数据。

用消息队列去删,做延迟删。

为什么使用工厂模式

https://blog.csdn.net/qq_36186690/article/details/82945749

为什么使用抽象类

封装、继承、多态,子类有不同行为。便于扩展
如果是非抽象的父类,就会导致子类重载父类方法会影响父类的行为。里氏替换原则
当一个类实现接口而不想实现接口全部方法的时候可以用抽象类。然后子类再实现抽象父类未实现的方法
子类必须实现抽象父类的方法,如果是非抽象父类的话,就没有约束性了。
传参的时候可以传抽象类型,而不用传确定的类型。
具有一些公共的特性实体提取抽象,通过继承抽象实现多态

为什么使用接口

接口隔离原则,为了以后好扩展
面向接口,你依赖的是接口。具体的实现逻辑在实现类实现。
哪天业务修改了,你只要换了实现类就行了。依赖方这边无需任何修改
传参的时候可以传接口类型,而不用传确定的类型。

在同一个类中,一个方法调用另外一个有注解的方法,注解失效的原因和解决方法
@Service  
class A{  
    @Transactinal  
    method b(){}  
      
    method a(){   
        b();  
    }  
}

//Spring扫描注解后,创建了另外一个代理类
class proxy$A{  
    private A target;  

    method b() {    
        startTransaction();  // 方法增强
        target.b();  
    }  
  
    method a() {   
        target.a(); // 方法未增强
    }  
}  

把这两个方法分开到不同的类中;
把注解加到类名上面,相当于每个方法都加了事务;
参考:
https://blog.csdn.net/liangweihua123/article/details/81001138
https://www.cnblogs.com/csnjava/p/13366051.html

数据插入的四种模式:

Insert into,Replace Into,Insert ignore,on duplicate key update
四种模式的区别:
1、insert into 最普遍的插入,如果表中存在主键相同的数据,执行会报错。
2、replace into 如果表中存在与主键相同的数据,则替换掉该主键的记录,反之则插入(存在就替换,反之插入)
3、insert ignore 如果表中存在主键相同的数据不在插入该条数据,反之则插入(存在则忽略,反之插入)
4、insert into *** on duplicate key update 如果表中存在该记录,则按新的数据进行修改,不存在则插入。(与replace into的区别在于:replace是完全替换成新的数据记录,此处是修改不同的地方,新纪录中没有的部分依然采用老记录中的数据。)

垃圾清除算法

标记-清除算法
标记和清除的效率都不高,内存碎片,标记清除后会产生大量不连续的内存碎片,内存碎片太多会导致当程序需要分配较大的对象时,无法找到足够的连续内存而不得不提前触发 GC
复制算法,浪费空间
标记-整理算法
分代收集算法

Java 中有哪几种引用?

强引用,不会回收,OOM 隐患
软引用,对于软引用关联的对象,在系统即将发生内存溢出前,会把这些对象列入回收范围中进行回收,如果回收后还没有足够的内存,就会抛出内存溢出异常。SoftReference
弱引用,被弱引用关联的对象只能生存到下一次 GC 前,发现即回收。WeakReference
虚引用,无法通过虚引用取得一个对象实例,虚引用的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。PhatomReference

在 Java 中,不同内存区域中可作为 GC Roots 的对象包括下面几种

1.虚拟机栈
虚拟机栈的栈帧中的局部变量表中引用的对象,比如某个方法正在使用的类字段。

2.方法区
类静态属性引用的对象
常量引用的对象

3.本地方法栈
本地方法栈中 Native 方法引用的对象。

在很大的事务中,commit提交时那么快

因为redo log 每秒都会刷新一次磁盘,不是等到最后一起刷新。

String

String str="Java";JVM 首先会检查该对象是否在字符串常量池中,如果在,就返回该对象引用,否则新的字符串将在常量池中被创建,这种方式可以减少同一个值的字符串对象的重复创建,节约内存。

String str = new String("Java") 这种方式,首先在编译类文件时,“Java”常量字符串将会放入到常量结构中,在类加载时,“Java”将会在常量池中创建;其次,在调用 new 时,JVM 命令将会调用 String 的构造函数,同时引用常量池中的“Java”字符串,在堆内存中创建一个 String 对象,最后 str 将引用 String 对象。
https://www.jianshu.com/p/1a9fbef534b4
别再问我 new 字符串创建了几个对象了!我来证明给你看!

为什么新生代会采用复制算法?

新生代的对象朝生夕死,大约90%的新建对象可以被很快回收,复制算法成本低,同时还能保证空间没有碎片。虽然标记整理算法也可以保证没有碎片,但是由于新生代要清理的对象数量很大,将存活的对象整理到待清理对象之前,需要大量的移动操作,时间复杂度比复制算法高。

为什么会有新生代?

如果不分代,所有对象全部在一个区域,每次GC都需要对全堆进行扫描,存在效率问题。分代后,可分别控制回收频率,并采用不同的回收算法,确保GC性能全局最优。

YGC的原理

1、从GC Root扫描对象,对存活对象进行标注
2、将存活对象复制到S1区或者晋升到Old区

http的options请求是什么

1、获取服务器所支持的通信方式
2、跨域请求中,options请求是浏览器自发起的preflight request(预检请求),检测请求是否可以被浏览器接受。

OOM问题排查

开启 +XX:dumpOnOutOfMemmeryError
查看堆存储快照,调整内存分配和JVM参数,排除是不是递归导致栈溢出,JVM堆也不宜设置过大,过大会导致gc停顿时间过长。

命令:jps、jinfo、jstat、jstack、jmap
可视化界面:JConsole、JVisualvm、HA、GCHisto、GCViewer

OOM产生原因

当JVM因为没有足够的内存来为对象分配空间并且垃圾回收器也已经没有空间可回收。
内存分配的少了,内存泄露或者内存溢出。
数据库连接,servetsocket,fileinputstream,磁盘文件读写,threadlocal
内存泄露:使用完的内存没有释放,导致虚拟机不能再次使用该内存
内存溢出:申请的内存超出了JVM能提供的内存大小
静态HashMap,可能有代码不断往静态变量的容器里加元素
https://blog.csdn.net/qq_42447950/article/details/81435080

服务器响应变慢问题排查

网络不好,大量磁盘IO,慢sql,死锁,依赖的其他服务慢,内存占用过多,垃圾回收频繁,线程太多,上下文切换频繁,cpu占用过多,比如出现了死循环。

为什么要熔断降级

防止整个链路的服务都受影响,当前业务又是非核心业务可以快速失败,别阻塞其他业务

优化多线程上下文切换

减少锁的持有时间,降低锁的粒度,减少并发冲突,非阻塞乐观锁替代竞争锁,分段锁,读写分离
线程池的线程数量设置不宜过大,设置过大会因为锁竞争导致上下文切换频繁,减少 Java 虚拟机的垃圾回收,垃圾回收会导致上下文切换
避免长时间等待,使用 Object.wait (long)设置等待超时时间。
用 Executors.newCachedThreadPool() 创建的线程池,该线程池会复用其内部空闲的线程来处理新提交的任务,如果没有,再创建新的线程(不受 MAX_VALUE 限制),这样的线程池如果碰到大量且耗时长的任务场景,就会创建非常多的工作线程,从而导致频繁的上下文切换。因此,这类线程池就只适合处理大量且耗时短的非阻塞任务。
https://blog.csdn.net/sinat_27143551/article/details/103033608

自动关单

1.定时器扫描订单,效率低,特别浪费资源,分库情况下实现比较麻烦
2.消息队列延迟推送,系统解耦,稳定性高,引入新的组件,增加维护成本
3.Redis监听Key失效
https://www.yuque.com/u1513751/redis/qvyy6p

网络7层架构
TCP/IP原理
TCP三次握手/四次挥手
HTTP原理
CDN原理

Spring 框架中的单例Beans是线程安全的么?

24075190-aa274f82f685e625.png

方志朋博客

相关文章

网友评论

      本文标题:【JAVA】面试题整理

      本文链接:https://www.haomeiwen.com/subject/kdajnktx.html