面试1

本文深入探讨了SpringMVC的执行流程,从用户请求到响应的完整过程。同时,详细阐述了线程与进程的关系,Java线程的六种状态及其转换,以及反射机制在实际应用中的作用。还介绍了如何创建自定义注解,TreeSet和ArrayList的区别,以及序列化和反序列化的功能。最后,讲解了Java中线程同步的wait和notify方法,并总结了MySQL的四种事务隔离级别及其对并发操作的影响。
摘要由CSDN通过智能技术生成

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

一、面试

1.SpringMVC的执行流程

在这里插入图片描述
在这里插入图片描述
1.用户发送请求到前端控制器DispatcherServlet;
2.前端控制器DispatcherServlet收到请求调用HandlerMappering处理器映射器;
3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView。
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、 ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户。

2.线程与进程的关系

每一个进程中都至少包含最少一个线程,线程是进程中执行运算的最小单位,也是执行处理机调度的基本单位。
每一个进程中都有自己的地址空间,如内存、cpu等。进程是资源分配的最小单位。
当我们对资源的保护管理要求比较高的时候,建议使用多进程,当然存在的开销也会比较大,反过来,如果频繁切换下,对资源的保护管理要求不那么高,或者开销有限,使用多线程会比较方便。

3.java的线程状态

在这里插入图片描述
共有六种状态
new(新建状态),runnable(就绪状态和运行状态),blocked(阻塞状态),waiting(阻塞状态),timed waiting(阻塞状态),terminated(终止状态)

需要注意的是在new 完之后 ,调用start()方法之后并不代表执行run方法。而是进入就绪状态等待cpu的调度。

1,当进入synchronized同步代码块或同步方法时,且没有获取到锁,线程就进入了blocked状态,直到锁被释放,重新进入runnable状态
2,当线程调用wait()或者join时,线程都会进入到waiting状态,当调用notify或notifyAll时,或者join的线程执行结束后,会进入runnable状态
3,当线程调用sleep(time),或者wait(time)时,进入timed waiting状态,当休眠时间结束后,或者调用notify或notifyAll时会重新runnable状态。
4,程序执行结束,线程进入terminated状态

补充:关于notify与notifyAll的区别
java中提供了两种方法来唤醒在某些条件下等待的线程,可以用这两个的任意一个。需要注意的是:
当你使用notify时,会随机唤醒一个线程。注意是随机。
当使用notifyAll时,会唤醒所有的线程。

知乎上看到的:

先说两个概念:锁池和等待池
锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象
的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。

等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池中Reference:java中的锁池和等待池

然后再来说notify和notifyAll的区别 如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

综上,所谓唤醒线程,另一种解释可以说是将线程由等待池移动到锁池,notifyAll调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。

而notify只会唤醒一个线程。有了这些理论基础,后面的notify可能会导致死锁,而notifyAll则不会的例子也就好解释了

4.java反射

JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
具体的应用比如说spring的依赖注入,拦截器等。

5.如何创建自定义注解

java.lang.annotation中提供了元注解,可以使用这些注解来定义自己的注解。主要使用的是Target和Retention注解
java.lang.reflect.AnnotationElement接口则提供了功能可以拿到我们定义的注解。
Target:描述了注解修饰的对象范围,取值在java.lang.annotation.ElementType定义,常用的包括:
METHOD:用于描述方法
PACKAGE:用于描述包
PARAMETER:用于描述方法变量
TYPE:用于描述类、接口或enum类型
Retention:表示注解保留时间长短
SOURCE:在源文件中有效,编译过程中会被忽略
CLASS:随源文件一起编译在class文件中,运行时忽略
RUNTIME:在运行时有效
常用在登陆验证、打印日志等。

6.tree set 如何去重

tree set是使用compareTo来进行排序和去重的.比较的是自己的某个属性与对象属性的差值,如果返回的是0,则说明重复。如果是正数则往后面排,如果是负数则往前面排。可以通过实现compareable接口来进行对compareTo方法的重写,定义排序及去重规则。

补充:hashSet去重原理。
比较hashcode 然后再通过equals比较。也可以通过改变这两个来实现自定义。

7.arraylist与linklist的区别

ArrayList是数组,是一块连续的内存空间。
LinkList 是双向链表,不是一块连续的内存空间。

ArrayList因为是一块连续的内存空间,所以查找快,方便寻址。但是插入、删除慢,因为需要发生数据迁移。
LinkList查找慢,因为需要通过指针一个一个的进行查找。但是插入、删除快,
因为只需要改变前后节点的指针指向即可。
这只是比较笼统的概念
插入删除跟查找也是要分情况的,比如插入、删除在中间部分或者在末尾部分。查找第几个元素或者某个元素在什么位置不同的情况也是不一样的。
补充:arraryList的扩容机制,本身的默认值是10,在添加第11个元素时时会进行位运算扩容到1.5倍。
linklist的每一个对象中会存储三个空间,两个存储指针指向前后,一个存储对象。

8.序列化和反序列化的作用

序列化就是把对象转换成字节序列的过程。
反序列化就是把字节序列恢复成对象的过程。

序列化就例如我们要把Java对象存储到硬盘上或者传送给网络上的其他计算机,我们需要调用outputstream的writeobject方法来将Java对象转换成某个格式的字节流,但是要求必须实现serializable接口,这样在编译的时候才会进行特殊处理,该接口没有需要实现的方法只是作为对象可被序列化的标注。

Externalizable接口继承自 Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以 采用默认的序列化方式 。

反序列化调用的方法是inputstream的readobject。都在java.io.object下。

9.Spring如何创建对象及生命周期

暂无

10.mysql隔离级别

为了解决并发的情况下,数据的安全性问题。
Read_Uncomited(脏读):读取过期的数据,就是一个事物读到另一个事务未提交的新数据,最低隔离级别,一切皆有可能;
Read_Commited(幻读):读取临时的数据,就是一个事物在进行修改全表的时候,另一个事务对数据进行了新增,从而第一个事务的执行完后发现还有没有修改的数据,就好像发生了幻觉一样;
RepeaTable_Read(不可重复读):就是在同一个事务中先后执行两条一样的select语句,之间没有执行过Del 语句但先后结果不一样,这就是不可重复读;;
Serializable:串行化,最高隔离界别,杜绝一切隐患,但效率较低;

知乎:
READ UNCOMMITTED 读未提交,脏读、不可重复读、幻读有可能发生。READ COMMITTED 读已提交,可避免脏读的发生,但不可重复读、幻读有可能发生。
REPEATABLE READ 可重复读,可避免脏读、不可重复读的发生,但幻读有可能发生。
SERIALIZABLE 串行化,可避免脏读、不可重复读、幻读的发生,但性能会影响比较大。

脏读:未提交但是就可以读到数据了,就会导致数据出现一些错误的计算。

不可重复读:同一事务执行的比较长,然后期间提交了两次数据,那么这个事务中就会出现两次不一样的数据。或者就是在同一个事务中先后执行两条一样的select语句,之间没有执行过Del 语句但先后结果不一样,这就是不可重复读。

幻读:在一个事务修改表的时候,另一个事务对表进行了增加。但是第一个事务执行完成后发现有一些数据没有进行修改,这就是幻读。

总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值