面试问题
1.多线程会出现的问题?解决办法?
1.1原子性
即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
原子操作:即不会被线程调度机制打断的操作
解决办法:
1.使用原子类
2.使用synchronize或者lock来保证原子性
1.2可见性
可见性:指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
解决办法:
1.使用 volatile 这个关键字。当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值
2.Java的锁机制如synchronize和lock,加锁可以保证在同一时刻只有一个线程在执行同步代码块
3.有序性:
有序性:即程序执行的顺序按照代码的先后顺序执行,
指令重排序:一般来说,处理器为了提高程序运行效率,可能会对输入代码进行优化,它不保证程序中各个语句的执行先后顺序同代码中的顺序一致,但是它会保证程序最终执行结果和代码顺序执行的结果是一致的。指令重排序不会影响单个线程的执行,但是会影响到线程并发执行的正确性。
解决办法:在Java里面,可以通过volatile关键字来保证一定的“有序性”,因为可以禁止指令重排序。另外可以通过synchronized和Lock来保证有序性,
2.数据库设计三范式
三大范式只是一般设计数据库的基本理念,可以建立冗余较小、结构合理的数据库。如果有特殊情况,当然要特殊对待,数据库设计最重要的是看需求跟性能,需求>性能>表结构。所以不能一味的去追求范式建立数据库
2.1 第一范式(确保每列保持原子性)
数据库表中的所有字段值都是不可分解的原子值
2.2 第二范式(确保表中的每列都和主键相关)
在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中
2.3 第三范式(确保每列都和主键列直接相关,而不是间接相关)
3.索引的类型
索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息
原理:对添加索引的字段进行拷贝,并把它放进B+树(MySQL)中,消耗空间来获取时间。
主键索引(primary key)
一个表中,最多有一个主键索引
唯一索引(unique)
普通索引(index)
全文索引(fulltext)
4.索引失效的情况
1、like 以%开头,索引无效;当like前缀没有%,后缀有%时,索引有效。
2、or语句前后没有同时使用索引。当or左右查询字段只有一个是索引,该索引失效,只有当or左右查询字段均为索引时,才会生效
3、在索引字段上使用not,!=。不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描。 优化方法: key<>0 改为 key>0 or key<0。
4、对索引字段进行计算操作、字段上使用函数
5、在索引列上使用 IS NULL 或 IS NOT NULL操作
5.查看是否使用索引的方法
使用explain命令加在要分析的sql语句前面,在执行结果中查看key这一列的值,如果为NULL,说明没有使用索引。
6.springboot启动过程
1、创建SpringApplication对象,使用SPI技术加载加载 ApplicationContextInitializer、ApplicationListener 接口实例
2、调用SpringApplication.run() 方法
3、调用createApplicationContext()方法创建上下文对象,创建上下文对象同时会注册spring的核心组件类(ConfigurationClassPostProcessor 、AutowiredAnnotationBeanPostProcessor 等)。
4、调用refreshContext() 方法启动Spring容器和内置的Servlet容器
7.mysql事务四大属性
1.原子性:事务包含的所有操作要么全部成功,要么全部失败回滚
2.一致性:一个事务执行之前和执行之后都必须处于一致性状态
3.隔离性:多个并发事务之间要相互隔离
4.持久性:一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的
8.mysql事务的隔离级别
- Read uncommitted(未授权读取、读未提交)
- Read committed(授权读取、读提交)
不允许脏读;Oracle、pistgreSql默认 - Repeatable read(可重复读取)
不允许脏读,不允许不可重复读;MySQL默认 - Serializable(序列化)
不允许脏读,不允许不可重复读,不允许幻读
9.并发情况下可能会出现的问题
1.脏读(Dirty Read):A事务读取B事务尚未提交的数据并在此基础上操作,而B事务执行回滚,那么A读取到的数据就是脏数据。
2.不可重复读(Non-repeatable Reads) :一个事务对同一行数据重复读取两次,但是却得到了不同的结果。事务T1读取某一数据后,事务T2对其做了修改,当事务T1再次读该数据时得到与前一次不同的值。
3.幻读:指两次执行同一条 select 语句会出现不同的结果,第二次读会增加一数据行,并没有说这两次执行是在同一个事务中
10.饿汉式单例类与懒汉式单例类比较
饿汉式单例类在类被加载时就将自己实例化,它的优点在于无须考虑多线程访问问题,可以确保实例的唯一性
懒汉式单例类在第一次使用时创建,无须一直占用系统资源,实现了延迟加载,但是必须处理好多个线程同时访问的问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费大量时间,这意味着出现多线程同时首次引用此类的机率变得较大,需要通过双重检查锁定等机制进行控制,这将导致系统性能受到一定影响
11.单例的优缺点
优点:
1.确保所有的对象都访问一个实例
2.单例模式具有一定的伸缩性,类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。
3.提供了对唯一实例的受控访问。
4.节约系统资源
5.避免对共享资源的多重占用。
缺点:
1.不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
2.由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
3.单例类的职责过重,在一定程度上违背了“单一职责原则”。
12.spring创建对象的生命周期
1.实例化 Instantiation
2.属性赋值 Populate
3.初始化 Initialization
4.销毁 Destruction