凡科
mysql默认的事务隔离级别是什么?你如何理解可重复读?
可重复读
对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改(别的事务修改并且提交了也没有影响),否则他每次读取到的都是事务开启时的值。
mysql联合索引有什么好处
“一个顶三个”。建了一个(a,b,c)的复合索引,那么实际等于建了(a),(a,b),(a,b,c)三个索引,因为每多一个索引,都会增加写操作的开销和磁盘空间的开销。对于大量数据的表,这可是不小的开销!
覆盖索引。同样的有复合索引(a,b,c),如果有如下的sql: select a,b,c from table where a=1 and b = 1。那么MySQL可以直接通过遍历索引取得数据,而无需回表,这减少了很多的随机io操作。减少io操作,特别的随机io其实是dba主要的优化策略。所以,在真正的实际应用中,覆盖索引是主要的提升性能的优化手段之一
索引列越多,通过索引筛选出的数据越少。有1000W条数据的表,有如下sql:select * from table where a = 1 and b =2 and c = 3,假设假设每个条件可以筛选出10%的数据,如果只有单值索引,那么通过该索引能筛选出1000W*10%=100w 条数据,然后再回表从100w条数据中找到符合b=2 and c= 3的数据,然后再排序,再分页;如果是复合索引,通过索引筛选出1000w *10% *10% *10%=1w,然后再排序、分页,哪个更高效,一眼便知。
什么是顺序IO和随机IO
顺序IO是指读写操作的访问地址连续。在顺序IO访问中,硬盘所需的磁道搜索时间显着减少,因为读/写磁头可以以最小的移动访问下一个块。数据备份和日志记录等业务是顺序IO业务。
随机IO是指读写操作时间连续,但访问地址不连续,随机分布在磁盘的地址空间中。产生随机IO的业务有OLTP服务,SQL,即时消息服务等。
GC有两种:Minor GC和Full GC。
包括几个垃圾回收算法。
标记-清除(Mark-sweep)
算法和名字一样,分为两个阶段:标记和清除。标记所有需要回收的对象,然后统一回收。这是最基础的算法,后续的收集算法都是基于这个算法扩展的。
不足:效率低;标记清除之后会产生大量碎片。
复制(Copying)
此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。此算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不会出现“碎片”问题。当然,此算法的缺点也是很明显的,就是需要两倍内存空间。
标记-整理(Mark-Compact)
此算法结合了“标记-清除”和“复制”两个算法的优点。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,清除未标记对象并且把存活对象“压缩”到堆的其中一块,按顺序排放。此算法避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题。
分代收集算法。
有看过GC的日志,出现OOM你怎么解决?
-XX:+HeapDumpOnOutOfMemoryError
原因分析
Javaheap space 错误产生的常见原因可以分为以下几类:
1、请求创建一个超大对象,通常是一个大数组。
2、超出预期的访问量/数据量,通常是上游系统请求流量飙升,常见于各类促销/秒杀活动,可以结合业务流量指标排查是否有尖状峰值。
3、过度使用终结器(Finalizer),该对象没有立即被 GC。
4、内存泄漏(Memory Leak),大量对象引用没有释放,JVM 无法对其自动回收,常见于使用了 File 等资源没有回收。
解决方案
针对大部分情况,通常只需要通过 -Xmx 参数调高 JVM 堆内存空间即可。如果仍然没有解决,可以参考以下情况做进一步处理:
1、如果是超大对象,可以检查其合理性,比如是否一次性查询了数据库全部结果,而没有做结果数限制。
2、如果是业务峰值压力,可以考虑添加机器资源,或者做限流降级。
3、如果是内存泄漏,需要找到持有的对象,修改代码设计,比如关闭没有释放的连接。
OOM处理
获取Heap Dump
CMS了解吗
java 的 instanceof 关键字
java中,instanceof运算符的前一个操作数是一个引用变量,后一个操作数通常是一个类(可以是接口),用于判断前面的对象是否是后面的类,或者其子类、实现类的实例。如果是返回true,否则返回false。
如果一个类的实例是这个类本身的实例,那么它也是它的父类、它的父类的父类的实例,也是由它实现的接口的实例
且instanceof左边操作元显式声明的类型与右边操作元必须是同种类或右边是左边父类的继承关系 。
Spring AOP,用了哪个设计模式? 如果让你自己去实现类似于Spring AOP的功能,你怎么实现?
动态代理。
实现方法:实现InvocationHandler与实现MethodInterceptor。
public class AccountAdvice implements InvocationHandler {
//目标对象
private IAccountService target;
public AccountAdvice(IAccountService target) {
this.target = target;
}
/**
* 代理方法, 每次调用目标方法时都会进到这里
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
return method.invoke(target, args);
}
/**
* 前置增强
*/
private void before() {
System.out.println("对转账人身份进行验证.");
}
}
public class AccountAdvice implements MethodInterceptor {
/**
* 代理方法, 每次调用目标方法时都会进到这里
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
before();
return methodProxy.invokeSuper(obj, args);
// return method.invoke(obj, args); 这种也行
}
/**
* 前置增强
*/
private void before() {
System.out.println("对转账人身份进行验证.");
}
}
平时写代码用过设计模式吗,关于设计模式在JDK源码的应用你了解多少。
原型模式 (通过创建方法识别,返回具有相同属性的其他实例)
java.lang.Object.clone()(必须实施java.lang.Cloneable)
装饰器模式 (通过创作方法识别采用相同抽象/接口类型的实例,添加额外的行为)所有子类java.io.InputStream,OutputStream,Reader和Writer有一个构造函数取相同类型的实例。
Flyweight(享元)作用:共享对象,节省内存(1)Integer.valueOf(int i);Character.valueOf(char c)(2)String常量池
Observer(观察者) 作用:通知对象状态改变
Swing中的Listener
详见此文
扩展:Spring中用到了那些设计模式。
工厂:工厂模式, Spring lOC核心的设计模式的思想体现,他自己就是一个大的工厂,把所有的bean实例都给放在了 Sping容器里(大工厂),如果你要使用bean,就找 Sping容器就可以了,你自己不用创建对象了。
单例:Spring默认来说,对每个bean走的都是一个单例模式,确保说你的一个类在系统运行期间只有一个实例对象,只有一个bean,用到了一个单例模式的思想,保证了每个bean都是单例的
代理:如果说你要对一些类的方法切入一些增强的代码,会创建一些动态代理的对象,让你对那些目标对象的访问,先经过动态代理对象,动态代理对象先做一些增强的代码,调用你的目标对象。在设计模式里就是代理模式的体现和运用,让动态代理的对象去代理了你的目标对象,在这个过程中做一些增强的访问。
ConcurrentHashMap如何保证线程安全?
在JDK1.7以及之前的版本里,分段
[数组1],[数组2],[数组3]->每个数组都对应一个锁,分段加锁
多个线程过来,线程1要put的位置是数组1[5],线程2要put的位置是数组2[21]两者可以并发执行。
JDK1.8以及之后,做了一些优化和改进,锁粒度的细化
[一个大的数组],数组里每个元素进行put操作,都是有一个不同的锁,刚开始进行put的时候,如果两个线程都是在数组[5]这个位置进行put,这个时候,对数组5这个位置进行put的时候,采取的是CAS的策略。
同一个时间,只有一个线程能成功执行这个CAS,就是说他刚开始先获取一下数组5这个位置的值,null,然后执行CAS,线程1,比较一下,put进去我的这条数据,同时间,其他的线程执行CAS,都会失败。
分段加锁,通过对数组每个元素执行cAs的策略,如果是很多线程对数组里不同的元素执行put,大家是没有关系的,如果其他人失败了,其他人此时会发现说数组[5]这位置,刚才已经有人放进去值了,就需要在这个位置基于链表+红黑树来进行处理, synchronized(数组[5]),加锁,基于链表或者是红黑树在这个位置插进去自己的数据.
你看的最多的专业书是哪些?(Java疯狂讲义以及深入理解Java虚拟机)
什么是可重入性,为什么说 Synchronized 是可重入锁?
可重入性是锁的一个基本要求,是为了解决自己锁死自己的情况。
对 Synchronized 来说,可重入性是显而易见的,在执行 monitorenter 指令时,如果这个对象没有锁定,或者当前线程已经拥有了这个对象的锁(而不是已拥有了锁则不能继续获取),就把锁的计数器 +1(释放锁减1),其实本质上就通过这种方式实现了可重入性。
你刚才提到获取对象的锁,这个“锁”到底是什么?如何确定对象的锁?
“锁”的本质其实是 monitorenter 和 monitorexit 字节码指令的一个 Reference 类型的参数,即要锁定和解锁的对象。我们知道,使用 Synchronized 可以修饰不同的对象,因此,对应的对象锁可以这么确定。
1.如果 Synchronized 明确指定了锁对象,比如 Synchronized(变量名)、Synchronized(this) 等,说明加解锁对象为该对象。
2.如果没有明确指定:
若 Synchronized 修饰的方法为非静态方法,表示此方法对应的对象为锁对象;
若 Synchronized 修饰的方法为静态方法,则表示此方法对应的类对象为锁对象。
注意,当一个对象被锁住时,对象里面所有用 Synchronized 修饰的方法都将产生堵塞,而对象里非 Synchronized 修饰的方法可正常被调用,不受锁影响。
cvte
HTTPS加密的过程?
(1)浏览器把自己支持的加密规则发送给网站。
(2)网站从这套加密规则里选出来一套加密算法和hash算法,然后把自己的身份信息用证书的方式发回给浏览器,证书里有网站地址、加密公钥、证书颁发机构。
(3)浏览器验证证书的合法性,然后浏览器地址栏上会出现一把小锁浏览器接着生成一随机数密码,然后用证书里的公钥进行加密,这块走的非对称加密;用约定好的hash算法生成握手消息的hash值,然后用密码对消息进行加密,然后把所有东西都发给网站,这块走的是对称加密。
(4)网站用本地的私钥对消息解密取出来密码,然后用密码解密浏览器发来的握手消息,计算消息的hash值,并验证与览器发送过来的hash值是否一致,最后用密码加密一段握手消息,发给浏览器。
(5)浏览器解密握手消息,然后计算消息的hash值,如果跟网站发来的hash一样,握手就结束,之后所有的数据都会由之前浏览器生成的随机密码,然后用对称加密来进行进行加密。
常用的非对称加密是RSA算法,对称加密是AES、RC4等,hash算法就是MD5
高校闲置物品小程序有那些表,他们之间的关系是怎么样的?
CAS(Compare and Swap,即比较和交换)
AQS( AbstractQueuedSynchronizer抽象队列同步器)
非公平锁(默认)
公平锁(ReentrantLock lock = new ReetrantLock(true);)
HashMap的put()逻辑
HashMap多线程put出现死锁原因。
String.intern()
面试题汇总
synchronized与ReenterantLock的区别
补充:使用位置上: synchronized可以在方法上、代码段上使用、ReenterantLock只能在代码段上使用。
进程和线程分别是什么?
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
线程和进程的区别
什么时候选择线程,什么时候选择进程呢?
什么是上下文切换?
CPU通过分配时间片来执行任务,当一个任务的时间片用完,就会切换到另一个任务。在切换之前会保存上一个任务的状态,当下次再切换到该任务,就会加载这个状态。
——任务从保存到再加载的过程就是一次上下文切换。
切出: 一个线程被剥夺处理器的使用权而被暂停运行
切入: 一个线程被系统选中占用处理器开始或继续运行
请问什么是逻辑地址?什么是物理地址?
答:逻辑地址:在计算机中,访内指令给出的地址(操作数)叫逻辑地址,也叫相对地址。
逻辑地址由两个16位的地址分量构成,一个为段基值,另一个为偏移地址。
物理地址:在存储器里以字节为单位存储信息,为了正确地存放或取得信息,每一个字节单元给以一个唯一的存储器地址,称为物理地址,又叫实际地址或绝对地址。物理地址=段基值×10H+偏移地址。
说一下你对松耦合和高内聚的理解
内聚:一个模块内各个元素彼此结合的紧密程度
耦合:一个软件结构内不同模块之间互连程度的度量
低耦合
一个完整的系统,模块与模块之间,尽可能的使其独立存在。 也就是说,让每个模块,尽可能的独立完成某个特定的子功能。 模块与模块之间的接口,尽量的少而简单。 如果某两个模块间的关系比较复杂的话,最好首先考虑进一步的模块划分。
这样有利于修改和组合。
高内聚
在一个模块内,让每个元素之间都尽可能的紧密相连。 也就是充分利用每一个元素的功能,各施所能,以最终实现某个功能。 如果某个元素与该模块的关系比较疏松的话,可能该模块的结构还不够完善,或者是该元素是多余的。
内聚和耦合,包含了横向和纵向的关系。功能内聚和数据耦合,是我们需要达成的目标。横向的内聚和耦合,通常体现在系统的各个模块、类之间的关系,而纵向的耦合,体现在系统的各个层次之间的关系。
各人自扫门前雪,莫管他人瓦上霜解释高内聚低耦合
讲一下耦合和内聚的等级划分
非直接耦合
非直接耦合两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的。耦合度最弱,模块独立性最强。
数据耦合
数据耦合是指两个模块之间有调用关系,传递的是简单的数据值,相当于高级语言中的值传递。
标记耦合
标记耦合是指两个模块之间有调用关系,传递的是数据结构,如高级语言的数组名、记录名、文件名等这些名字即为标记,其实传递的是数据结构的地址。
控制耦合
控制耦合是指两个模块之间有调用关系,一个模块调用另一个模块时,传递的是控制变量,如(开关、标志)等,被调模块通过该控制变量的值有选择地执行块内某个功能。
外部耦合
外部耦合是指一组模块都访问同一全局简单变量,而且不通过参数表传递全局变量的信息,称之为外部耦合。
公共耦合
公共耦合是指一组模块都访问同一全局数据结构,称之为公共耦合。
内容耦合
内容耦合是指一个模块与另一个模块的内部属性有关,不经调用直接使用另一个模块的程序代码或内部数据,称之为内容耦合。
记忆口诀:内公外空标数非。
功能内聚
功能内聚指模块内所有元素共同完成一个功能,缺一不可。
顺序内聚
顺序内聚是指一个模块中各个元素必须顺序执行,前一功能元素的输出是下一功能元素的输入。
通信内聚
通信内聚是指一个模块的所有元素都在同一数据结构上操作,称之为通信内聚。
过程内聚
过程内聚是指模块完成多个需要按一定的步骤一次完成的功能。
时间内聚
时间内聚是指一个模块完成的功能必须在同一时间内执行,称之为时间内聚。
逻辑内聚
逻辑内聚是指模块内执行多个逻辑相似的功能,通过参数确定该模块完成哪一个功能。
偶然内聚
偶然内聚是指模块中的机能只是刚好放在一起,各机能之间唯一的关系是其位置在同一模块中。
记忆口诀:偶逻时过通顺功。
二叉树是线性结构吗?
答:不是。二叉树有多个直接后继所以其不是线性结构。
数据结构课程中数据的逻辑结构分为线性结构和非线性结构。简单地说,线性结构是n个数据元素的有序(次序)集合。
1.集合中必存在唯一的一个"第一个元素";
2.集合中必存在唯一的一个"最后的元素";
3.除最后元素之外,其它数据元素均有唯一的"后继";
4.除第一元素之外,其它数据元素均有唯一的"前驱"。
数据结构中线性结构指的是数据元素之间存在着“一对一”的线性关系的数据结构。
如(a0,a1,a2,…,an),a0为第一个元素,an为最后一个元素,此集合即为一个线性结构的集合。
相对应于线性结构,非线性结构的逻辑特征是一个结点元素可能对应多个直接前驱和多个后继。
TCP和UDP是什么?
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。
如何快速定位冲突的maven jar包
集成redisson实现分布式锁
redisson没有争抢成功的线程会一直自旋吗?
一致性hash
select、poll和epoll的区别
JVM常见的配置参数
微服务优势和劣势也讲一讲吧
讲一下G1垃圾回收器
讲一下G1垃圾回收器
面试题汇总
Java800面试题含答案
锁的种类
SQL优化
数据库范式
Linux命令