java 面试知识点突击-(51-60)

Posted 栗子~~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 面试知识点突击-(51-60)相关的知识,希望对你有一定的参考价值。

前言

  如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
  而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!


java 知识点扫盲目录

https://blog.csdn.net/weixin_38316697/article/details/121991582

java 面试知识点突击-(51-60)

51 spring 事务的实现方式与隔离机制?

51::01 实现方式

1、编程式:
2、申明式:@Transational
 即当一个方式上加上@Transational后,spring会基于这个类生成一个代理对象,
会将这个对象作为一个bean,当使用这个代理对象的这个方法时,如果这个方法上存在@Transational注解时,代理对象
会先把事务的自动提交设置为false,然后执行原本的逻辑,如果执行中没有异常,那么代理逻辑中会将事务提交,
如果出现异常,那么将事务进行回滚。

注:@Transational 默认回滚异常为RuntimeException和error进行回滚。

51::02 隔离机制

spring 事务的隔离级别就是数据库的隔离级别,外加一个默认级别。
1、read uncommitted (未提交读、脏读)

在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。

2、read committed(提交读、不可重复读) - oracle的默认级别

这是大多数数据库系统的默认隔离级别(但不是mysql默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。

3、repeatable read(可重复读) -mysql的默认级别

这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。

4、serializable(可串行化)

这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

5、默认级别是根据你选择的数据库的默认级别设置

注:如果spring设置隔离级别,那么以spring设置为准,如果spring设置的数据库不支持,效果以数据库为准。


52 spring 事务的传递方式?

【a】方法调【b】方法,我们以【b】方法的视角来看、有七种方式,如下:

序号传播行为描述
1PROPAGATION_SUPPORTS有事务就加入,没有就以非事务方式执行
2PROPAGATION_MANDATORY必须有事务,如果当前没有事务,则抛出异常
3PROPAGATION_REQUIRED如果有事务则加入,没有则新建
4PROPAGATION_REQUIRES_NEW开启新事务,老事务挂起
5PROPAGATION_NESTED事务嵌套执行
6PROPAGATION_NOT_SUPPORTED不开启事务,如果当前存在事务,就把当前事务挂起
7PROPAGATION_NEVER必须在没有事务中执行,如果当前有事务,则抛出异常

53 spring 事务什么时候会失效?

Spring的事务原理的是AOP,进行切面增强,失效的根本原因就是AOP不起作用了。

1、发生自调用 ,this对象不是代理类;
解决方法:将this变成所在类的代理类就行,或者使用带有@Autowired注解的对象
2、同类中方法调用;
其实这还是由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理
3、方法不是public的;
@Transational定义的时候就只能让public上使用
解决方案:如果非要在非public上使用,可以开始@Aspectj代理模式
4、数据库不支持事务;
5、没有被spring管理;
6、异常被吃掉,事务不会回滚;
7、使用@Transationa 设置错误;
如: propagation,rollbackFor设置错误
8、使用自定义切面把异常吃了,事务也不会回滚;


54 并发、并行、串行的区别

串行:时间上不可能重叠,一个一个任务运行,上一个任务没执行完,下一个任务就只能等待。
并行:时间上是重叠的,多个任务在同一时刻,互不干扰的同时运行。
并发:同一时间点只能有一个任务运行,允许多个任务彼此干扰,交替执行。

注:并发对于cpu来说,它也是串行执行的。


55 并发的三大特性

1)、原子性
简单来说,就是要不都执行,要不都不执行,因为cpu不可能中途停止在调用。
2)、可见性
可见性是指一个线程对共享变量的修改,对于另一个线程来说是否是可以看到的。即当多个线程进行操作共享数据时,可以保证内存中的数据可见。
3)、有序性
关键字:volatile、synchronized、final
防止指令重排。

原因:JVM在进行代码编译时,对于那些改变顺序之后不会对最终结果造成影响的代码,JVM不一定按照我们写的代码顺序进行执行,有可能将他们重新排序,但实际上重排序之后,虽然对变量的值没有造成影响,但是有可能出现线程安全。
注:JVM指令重排的机制是判断在单线程下结果会不会发生变化,如果发生变化,就不会重排。


56 为什么使用线程池,解释一下线程池的参数

56::01 为什么使用线程池?

1)核心原因就是降低资源消耗,提高线程的利用率。
2)提高响应速度,任务来了,直接有线程可用,省掉了线程的创建和销毁的消耗。
3)操作系统里的线程的个数是有限的,利于管理线程,例:复用,统一分配。

即:线程池将线程和任务解耦,线程是线程,任务是任务,摆脱了之前通过Tread创建线程时,一个线程必须一个任务的限制。

56::02 线程池参数详解

ThreadPoolExecutor(  int corePoolSize,
                     int maximumPoolSize,
                     long keepAliveTime,
                     TimeUnit unit,
                     BlockingQueue<Runnable> workQueue,
                     ThreadFactory threadFactory,
                     RejectedExecutionHandler handler)     
参数描述
corePoolSize:核心线程数量常驻线程,随着线程池的存在而存在,核心线程数最终的回收是随着线程池的回收而回收
maximumPoolSize:最大允许线程数量表示最大允许被创建的线程数
keepAliveTime、unit 超出线程的存活时间当超出核心线程数的其余线程,空闲一定时间后,被消除
workQueue 任务队列存放待执行的线程
handler 任务拒绝策略当任务队列已满,又有新的任务进来时,会回调此接口
threadFactory 线程工厂,用于创建线程当前线程数超过corePoolSize时,新的任务会处在等待状态,并存在workQueue中线程池内初初始没有线程,任务来了之后,会使用线程工厂创建线程

注:使用handler 任务拒绝策略有两种情况
第一种:当我们调用shutdown等关闭线程池的方法后,继续添加任务后就会触发handler 任务拒绝策略。
第二种:当达到最大线程数的时候,继续添加任务后就会触发handler 任务拒绝策略。


57 线程池处理流程?

简述:
corePoolSize 核心线程数量 都在运行的时候
进来的任务会存放于workQueue 任务队列
workQueue 任务队列满的时候
创建新的线程(不能大于maximumPoolSize最大允许的线程数)
当操作系统的线程数大于maximumPoolSize最大允许的线程数
触发handler 拒绝策略

流程图:


58 线程池中阻塞队列的作用,为什么是先添加队列,而不是先创建最大线程?

58::01 为什么使用阻塞队列?

一般队列,只能当做有限长度的缓存,如果超出就无法保存当前队列,而阻塞队列的话,通过阻塞可以保留想要继续入队的任务

阻塞队列,帮助我们阻塞线程,唤醒线程
即阻塞队列自带阻塞和唤醒功能,无需做额外处理,无任务执行时,线程池利用阻塞队列的take方法挂起,从而维持核心线程的存活,不至于一直占用cpu。

58::02 为什么是先添加队列,而不是先创建最大线程?

因为创建新线程的时候,会获取全局锁,影响整体效果,而添加队列里代价比较小。
目的在于,不去频繁的创建线程销毁线程,影响效率。


59 线程池中线程的复用原理

在线程池中,同一个线程可以利用阻塞队列中不断获取新任务来执行。
核心原理:

将Thread就行封装,不是每次执行任务都是调用线程的start()方法,而是让每个线程去执行一个循环任务,在任务中,不停的检查是否有任务执行,当有任务要执行时,调用run()方法,将run方法当成一个普通方法来执行.
即通过这种方式只使用固定线程就能将所有的任务的run方法串联起来。
注:调run方法是同步运行,调start()方法是异步执行。


60 java中的异常体系

最顶级的异常类Throwable,所有的异常类都来自于它。
Throwable下有两个子类:
1、 Exception
程序员能处理的错误;
1) RunTimeException 运行时异常,比如:空指针、下标越界
>>>> 发生在程序运行时,会导致当前线程执行失败。
2)CheckedException 检查异常
>>>> 发生在程序编译过程中,会导致编译不通过
2、 Error
程序员不能处理的错误,比如:堆溢出、栈溢出;
一旦出现错误,程序被迫停止进行


创作不易、点关注、不迷路

点击主页、更精彩 !!!

以上是关于java 面试知识点突击-(51-60)的主要内容,如果未能解决你的问题,请参考以下文章

java 面试知识点突击-(61-70)

java 面试知识点突击-(71-80)

java 面试知识点突击-(81-90)

java 面试知识点突击-(91-100)

Java面试手册V2.0+突击V3.0知识点整理(二十) 附封面图片

负载均衡(纯手写,极度适合巩固基础面试突击)