常见面试题
线程安全的理解
解释线程安全
线程安全的具体表现
原子性,有序性,可见性解释和导致这一现象的原因及解决方案
导致线程安全最主要的原因
简单来说,在多个线程去访问某个方法或者对象的时候,不管通过任何的方式的调用或者线程如何去交替执行,在程序中不做任何同步干预的情况下,这个方法或者对象的执行结果都能够按照预期的来反馈,那么这个类我们认为它是线程安全的,
实际上线程安全问题的具体表现它有三个方面,原子性,有序性和可见性:
原子性就是说一个线程执行的一系列程序指令操作的时候,它应该是不可中断的,因为一旦出现了中断,站在多线程这样一个角度来看,这1系列的程序指令会出现前后执行结果不一致的问题,而CPU的上下文切换是导致原子性问题的一个核心,而Jvm中提供了一个Synchronized关键字来去解决这样一个问题,
可见性就是说在多线的环境下,由于读和写是发生在不同的线程里面的,有可能会出现某个线程对共享变量的修改对其他线程不是实时可见的,导致可见性问题的原因有很多,比如说像CPU的高速缓存,CPU的指令重排序,编译器的指令重排序,
有序性就是说程序编写的指令顺序和最终CPU运行的指令顺序可能会出现不一致的这样一个现象,这个现象称为指令重排序,所以有序性也会导致可见性的这样一个问题,可见性和有序性可以通过volatile关键字来解决,
在我看来导致有序性,原子性和可见性问题的一个本质是计算机工程师为了最大化的提升CPU利率导致的,比如说为了提升CPU的利用率,设计了三级缓存,StoreBuffer,缓存行的预读机制,在操作系统里面设计的线程模型,在编译器里面设计的编译器的深度优化机制,以上呢就是我对这样一个问题的理解
什么是双亲委派
类的加载过程
涉及到的加载器及加载的目录
双亲委派机制的作用
关于这个问题,首先简单说一下类的加载过程,类的加载过程就是我们自己写的JAVA文件到最终运行,它必须要经过编译和类加载这两个阶段,而编译的过程就是把.java文件编译成.class文件,而类的加载过程就是把class文件加载到jvm的内存里面,装载完成以后会得到一个class对象,我们就可以使用new关键字来实例化这个对象,
而类的加载过程需要涉及到类加载器,JVM在运行的时候会产生三个类加载器,这三个类加载器组成了一个层级关系,每一个类加载器分别去加载不同作用范围的jar包,比如说像bootstrapclassloader,它主要是负责JAVA核心类库的加载,也就是java_ home下面lib下的jar包,
extensionclassloader的主要是负责加载ext目录下的一个jar包
applicationclassloader的主要是负责当前应用里面classpath下面的所有jar包
除了系统自己提供的加载器外,还可以通过实现classloader来实现自定义类加载器去满足一些特殊的场景需求
而所谓的双亲委托模型就是至底向上查找,至顶向下加载,比如说当我们需要加载一个class文件的时候,首先会去把这个class文件的查询和加载委派给父加载器执行,如果父加载器都无法加载,那么在尝试自己的加载这个class,
那么这样的好处我认为有两个,第一个是安全性,因为这种承接关系实际上代表的是一种优先级,也就是说所有的类加载优先要给到bootstrapclassloader,那么对于核心类库中的一些类就没有办法被破坏,比如说自己写一个java.lang.string,最终还是会交给启动类加载器,再加上每个类加载器的本身的一个作用范围,那么自己写的java.lang.string就没有办法去覆盖类库中的类,第二个我认为这种层级关系的设计,可以避免重复加载导致程序混乱的一些问题,因为如果父加载器已经加载过了,那么子类加载器就没有必要再去加载了。以上就是我对这个问题的理解
什么是聚集索引和非聚集索引
简单来说,聚集索引呢就是基于组件创建的索引,除了主机索引以外的其他索引统一称为非聚集索引,也叫2级索引。因为在印度b的擎里面呢,一张表的数据对应的物理文件本身就是按照b加速来组织的,而具体索引呢就是按照每张表的组件来构建这样一个加数,然后电子节的里面存储了这个表里面的每一行数据记录,所以基于udp c这个特征呢,聚集索引并不仅仅是一种索引类型,还代表了一种数据的存储方式,同时也意味着每个表里面必须要有一个组件,如果没有组件会默认选择或者添加一个隐藏列作为主键索引来存储这个表的数据行,一般情况是建议使用至尊ID作为主键,这的ID本身是具有连续性,使得对应的数据也会按照顺序存储在磁盘上,写入性能和解锁性能都很高,否的话,如果使用UI的手机ID,那么在频繁的插入数据的时候,就会导致随机磁盘io,从而会导致性能下降,不过需要注意的是呢音乐APP里面只能存在一个最集中,所以原因很简单,如果存在多个区域索引,那么意味着这个表里面的数据会存在多个副本,不仅会造成磁盘空间浪费,还会去导致数据的维护困难,因为在印度APP里面的组件索引,它是存储了一个表的完整数据,所以如果是基于非聚集索引来查询一下数据的时候,那么最终还是得需要访问组件索引来进行解锁以上就是我对这个问题的理解这个问题要回答的好呢还真不容易