Loading

Mybatis面试题大全

1.MyBatis是什么?

  1. Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,加载驱动、创建连接、创建statement等繁杂的过程,开发者开发时只需要关注如何编写SQL语句,可以严格控制sql执行性能,灵活度高。

  2. 作为一个半ORM框架,MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。

  3. 通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过java对象和 statementsql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回result的过程)。

  4. 由于MyBatis专注于SQL本身,灵活度高,所以比较适合对性能的要求很高,或者需求变化较多的项目,如互联网项目。

优点:

  1. 基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。

  2. 与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;

  3. 很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)。

  4. 能够与Spring很好的集成;

  5. 提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。

缺点:

  1. SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。

  2. SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

Mybatis和Hibernate的区别

 

  1. Mybatis 和 hibernate 不同 ,它不完全是一个 ORM 框架 ,因为 MyBatis 需要程序员自己编写 Sql 语句,Mybatis 直接编写原生态 sql, 可以严格控制 sql 执行性能, 灵活度高, 非常适合对关系数据模型要求不高的软件开发,因为这类软件需求变化频繁,一但需求变化要求迅速输出成果。 

  2. 映射关系:
    • MyBatis 是一个半自动映射的框架,配置Java对象与sql语句执行结果的对应关系,多表关联关系配置简单
    • Hibernate 是一个全表映射的框架,配置Java对象与数据库表的对应关系,多表关联关系配置复杂

2.#{}和¥{}的区别是什么?

 #{ } 是占位符,预编译处理,${ } 是拼接符,字符串替换

Mybatis在处理#{ }时,会对sql语句进行预处理,将sql中的#{ }替换为?号,调用PreparedStatement的set方法来赋值;

Mybatis在处理${ }时,就是把${ }直接替换成变量的值;

--Mybatis在处理#{}时

select id,name,age from student where id =#{id}

当前端把id值1传入到后台的时候,就相当于:

select id,name,age from student where id ='1'

--Mybatis在处理${}时

select id,name,age from student where id =${id}

当前端把id值1传入到后台的时候,就相当于:

select id,name,age from student where id = 1


3.MyBatis的编程步骤是什么样的?


1.创建SqlSessionFactory

2.通过SqlSessionFactory创建SqlSession

3.通过sqlsession执行数据库操作

4.调用session.commit()提交事务

5.调用session.close()关闭会话

4.Mybatis都有哪些Executor执行器?

三种基本的Executor执行器,SimpleExecutor  普通的执行器,执行update和select,就开启Statement对象,用完立刻关闭。

                                                ReuseExecutor    重用预处理语句

                                                BatchExecutor      重用语句并批量更新

 

5.Mybatis是否支持延迟加载?如果支持,他的实现原理是什么?

 


Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection值得就是一对多查询。

它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。

6.模糊查询like语句该怎么写?

使用CONCAT('%',#{question}.'%') 使用CONCAT()函数

使用bind标签:

<select id="listUserLikeUsername" resultType="com.jourwon.pojo.User">
<bind name="pattern" value="'%' + username + '%'" />
select id,sex,age,username,password from person where username LIKE #{pattern}
</select>
7.当实体类中的属性名和表中的字段名不一样,怎么办

 1.通过<resultMap>来映射字段名和实体类属性名的一一对应的关系

resultMap 叫做结果集的映射
 

<select id="getOrder" parameterType="int" resultMap="orderResultMap">
select * from orders where order_id=#{id}
</select>
<resultMap type="com.jourwon.pojo.Order" id="orderResultMap">
<!–用id属性来映射主键字段–>
<id property="id" column="order_id">
<!–用result属性来映射非主键字段,property为实体类属性名,column为数据库表中的属性–>
<result property ="orderno" column ="order_no"/>
<result property="price" column="order_price" />
</reslutMap>

2.起别名

1.属性名和字段名不一样的处理办法 比如 数据库中为pwd,在进行编写的时候用的是password,这样的话查询出来是空值。
处理办法 起别名 select id,name,pwd as password from mybatis.user where id = #{id}
 
什么是Mybatis的接口绑定?有哪些实现方式?
  接口绑定就是在Mybatis中任意定义接口,然后把接口里面的方法和SQL语句绑定
   有两种实现方式:通过xml里面写SQL来绑定
                                  用注解绑定
 
 使用Mybatis的mapper接口调用时有哪些要求?
1.Mapper接口方法名必须和Mapper.xml中定义的sql的id相同
2.Mapper.xml文件中的的namespace是mapper接口的类路径
 

通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗

Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。

Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略

Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?

 不同的Xml映射文件,配置了namespace,id可以重复,没有配置namespace,id就不能重复

简述Mybatis的Xml映射文件和Mybatis内部数据结构之间的映射关系?

Mybatis将所有Xml配置信息都封装到All-In-One重量级对象Configuration内部。在Xml映射文件中,<parameterMap>标签会被解析为ParameterMap对象,其每个子元素会被解析为ParameterMapping对象。<resultMap>标签会被解析为ResultMap对象,其每个子元素会被解析为ResultMapping对象。每一个<select>、<insert>、<update>、<delete>标签均会被解析为MappedStatement对象,标签内的sql会被解析为BoundSql对象。

Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?

第一种是使用<resultMap>标签,逐一定义列名和对象属性名之间的映射关系。

第二种是使用sql列的别名功能,将列别名书写为对象属性名,比如T_NAME AS NAME,对象属性名一般是name,小写,但是列名不区分大小写,Mybatis会忽略列名大小写,智能找到与之对应对象属性名,你甚至可以写成T_NAME AS NaMe,Mybatis一样可以正常工作。

有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。

Xml映射文件中,除了常见的select|insert|updae|delete标签之外,还有哪些标签?

<resultMap>、<parameterMap>、<sql>、<include>、<selectKey>,加上动态sql的9个标签,trim|where|set|foreach|if|choose|when|otherwise|bind等,其中<sql>为sql片段标签,通过<include>标签引入sql片段,<selectKey>为不支持自增的主键生成策略标签。

 MyBatis实现一对一,一对多有几种方式?
     

有联合查询和嵌套查询。联合查询是几个表联合查询,只查询一次,通过在resultMap里面的association,collection节点配置一对一,一对多的类就可以完成

嵌套查询是先查一个表,根据这个表里面的结果的外键id,去再另外一个表里面查询数据,也是通过配置association,collection,但另外一个表的查询通过select节点配置。

Mybatis是否可以映射到Enum枚举类

mybatis可以映射Enum枚举类,映射方式为自定义个TypeHandler,实现TypeHandler的setParameter()和getResult()接口方法。TypeHandler有两个作用,一是完成从java type到jdbc的转换,二是完成jdbcType到Javatype的转换。

Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理不?

         动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能 
           if/choose/when/otherwise/where/bind/set/foreach/trim
           Mybatis采用功能强大的基于OGNL的表达式来淘汰其他大部分元素,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql。
 

Mybatis是如何进行分页的?分页插件的原理是什么?

Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。

分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

select * from student,拦截sql后重写为:select t.* from (select * from student) t limit 0, 10

MyBatis 的分页功能是基于内存的分页,即先查询出所有记录,再按起始位置和页面容量取出结果。

 

MyBatis拦截器原理?

Mybatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能。Mybatis允许你在已映射语句执行过程中的某一点进行拦截调用,Mybatis允许使用插件来拦截的方法调用包括:Executor,ParameterHandler,ResultSetHandler,StatementHandler

比如在使用分页插件来完成Mybatis分页

       分页插件的原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,然后在sql语句添加对应的物理分页语句和物理分页参数。

 

看过MyBatis源码吗,请说说它的工作流程?

1.加载配置文件

2.生成SqlSessionFactory工厂

3.使用SqlSessionFactory工厂创建SqlSession对象

4.使用SqlSession创建Dao接口的代理对象

5.使用代理对象执行方法

6.关闭SqlSession,释放资源

 

 

 

 

什么是字符串常量池?   创建一个字符串时,JVM会首先去字符串常量池查找是否存在这个对象,如果存在,则不创建任何对象,,直接将这个对象的地址返回。如果不存在,就新创建一个对象,然后返回。       字符串常量池是JVM为了提升性能和减少内存消耗针对字符串专门开辟的一块区域。      为了避免字符串的重复创建
String为什么是不可变的?String在定义时候声明final类型String类全局变量都定义为private final类型,表明对象一旦初始化,属性值就无法改变
String对象真的不可变吗?那么,用什么方式可以访问私有成员呢? 没错,用反射,可以反射出String对象中的value属性, 进而改变通过获得的value引用改变数组的结构
String s = new String("xyz");究竟产生了几个对象,从JVM角度谈谈?1个或者两个如果字符串池没有xyz字符串,会在字符串池中创建,会在堆内存创建如果字符串有xyz字符串,则只会在堆内存中创建

String拼接字符串效率低,你知道原因吗?比如在循环里面连接字符串,+在for循环内部,每次执行就会创建一个StringBuilder,如果不断产生会占用大量资源,应该在程序中直接使用StringBuilder来连接字符串,StringBuilder对象直接进行append的话,可以节省创建和销毁创建对象的时间。

你真的了解String的常见API吗?获取字符串的长度   int length()将自负串里面的小写字母变成大写 toUpperCase()将字符串里面的大写字母变成小写字母toLowerCase()比较两个字符串  equals截取字符串 substring()连接两个字符串 contat()替换  replace()
浅析Java中的final关键字?final用于声明类,属性,方法 ,即属性不可变,方法不可覆盖,类不可继承
浅析Java中的static关键字?static关键字声明一个成员变量或者成员方法可以在没有所属的类的实例变量的情况下被访问。Java中static方法不能被覆盖,方法覆盖是运行时动态绑定的,static方法是编译时静态绑定的
你对Java中的volatile关键字了解多少?volatile是保证了可见性,有序性,没有原子性volatile只是保持线程的可见性,被volatile修饰,也就有两层含义:1.线程内的修改操作可以立马被其他线程看到 2.禁止重排序我们通过看被volatile修饰过后的编译源码可以看到有一个前缀指令.lock,这就是相当于一个内存屏障。  内存屏障有3个功能:1.保证内存屏障前的指令不会排到内存屏障的后面内存屏障后面的指令不会排到内存屏障的前面                                 2强制对缓存的修改操作立即写入主存                                 3.如果是写操作,会导致CPU中对应的缓存行失效

i++是线程安全的吗?如何解决线程安全性?线程不安全,都没有原子性对i++操作的方法加同步锁,同时只有一个线程执行i++操作

从字节码角度深度解析 i++ 和 ++i 线程安全性原理?    i++字节码:   j = i++是一个先压栈,先将本地变量i压栈,然后本地变量自增1,再将栈顶元素弹出写到本地变量j内。此时j还是为0. ++i字节码:  j = ++i的操作顺序是先将本地变量i自增一,然后再压栈,最后写入到j内。也就是此时j为i+1之后的内容。
请谈谈什么是CAS?Compare and swap 比较并交换CAS(compare and swap, 比较并交换),是原子操作的一种,可用于在多线程编程中实现不被打断的数据交换操作,从而避免多线程同时改写某一数据时由于执行顺序不确定性以及中断的不可预知性产生的数据不一致问题。简单来说,CAS可以保证多线程对数据写操作时数据的一致性。CAS的思想:三个参数,一个当前内存值V、旧的预期值A、即将更新的值B,当且仅当预期值A和内存值V相同时,将内存值修改为B并返回true,否则什么都不做,并返回false。CAS的缺点:CASABA问题,循环时间长开销大和只能保证一个共享变量的原子操作。其中ABA问题作为第三部分重点说明下。
从源码角度看看ArrayList的实现原理? Arraylist是基于数组存储的,数组有下标,可以通过数组的下标进行一次访问,所以查询速度快。增删效率低,因为定义数组的时候需要定义其长度,不灵活不方便数据的增,删。geter()和seter()方法快
手写LinkedList的实现,彻底搞清楚什么是链表?LinkedList的底层是链表结构,是双向链表。可以通过链表中的一个节点,可以访问到它的前驱节点和后继节点。所以add()和remove()效率高
Java中方法参数的传递规则?值传递,如果是基本类型传递基本类型的字面值的拷贝,会创建副本,参数如果是引用类型传递的是参数所引用的对象在堆中地址值的拷贝,也会产生副本
Java中throw和throws的区别是什么?throw用来明确的抛出一个异常throws用来表明可能抛出的各种异常throw语句用在方法体内,用来明确的抛出一个异常throws用于方法声明以后,表明可能抛出的各种异常,throws表示出现异常的一种可能性,不一定会发生这种异常。
重载和重写的区别?重载发生在子类和子类,方法名必须相同,参数列表不同,实现了一个方法,可以实现类似的功能重写发生在子类与父类,方法名,参数列表必须相同,子类的返回值要小于等于父类,抛出的异常范围要小于等于父类,子类的访问修饰符要大于等于父类,public,protected,default,private,父类如果是private,就不可以重写。父类和子类的方法必须一致

finally语句块你踩过哪些坑?finally快不管有没有捕获异常或者处理异常都是会执行的,finally块里面不能有return,如果有的话就返回的是finally里面的return的值了
为什么重写equals方法需同时重写hashCode方法?重写了equals方法必须重写hashCode方法,针对Set和Map集合:1.集合首先判断存储对象是不是唯一的           2.集合类判断两个对象是否相等,先用equals()方法判断是否相等,如果为true,还要判断HashCode返回值是否为true,如果为true,才认为两个对象相等

equals() 与 == 的区别?相等于如果是基本类型的话比较的值,如果是引用类型,比较的是内存地址equals()如果是Object.equals()和相等于类似,如果是String.equals()比较的值
StringBuffer和StringBuilder的区别,从源码角度分析?都是可变字符序列,都继承AbstractStringBuilderStringBuffer效率低,线程安全StringBuilder效率高,线程是不安全的看过StringBuffer源码可以看到,几乎所有的方法都加了synchronized,synchronized是用来加锁的,所以线城是安全的我们通过StringBuilder源码看到,基本上方法都没有用synchronized关键字修饰,当多线程访问时候,就会出现线程安全性问题。

你知道HashMap的数据结构吗?HashMap在jdk1.7底层是数组,链表,在jdk1.8是数组,链表,红黑树

为何HashMap的数组长度一定是2的次幂?
HashMap何时扩容以及它的扩容机制?HashMap是基于Hashing原理的,是通过Put()方法和get()方法来存储和获取元素的,HashMap只要不进行Put方法存储元素之前,HashMap就不会扩容。当用put方法传递键和值时候,我们先对对象调用Hashcode()方法计算并返回Hashcode,随后计算并返回的hashcode适用于找到Map数组的bucket位置来存储对象,如果bucket满了,就要进行扩容调用resize方法进行扩容,默认的负载因子为0.75,当一个map填满了75%的bucket时候,就会扩容,扩容后table大小变味了原来的两倍
HashMap的key一般用字符串,能用其他对象吗?一般用Integer,String这种不可变类当HashMap当key
HashMap的key和value都能为null么?如果key能为null,那么它是怎么样查找值的?HashMap的key和value都能为null
HashMap是线程安全的吗?如何实现线程安全?线程不安全,使用Collections的synchronizedMap方法包装一下                   使用ConcurrentHashmap,使用分段锁来保证线程安全
从源码角度分析HashSet实现原理?Hashset是基于HashMap实现的,有放入HashSet中的集合元素实际上由HashMap的key来保存,而HashMap的value则存储了一个PRESENT,它是一个静态的Object对象。如果向HashSet中添加一个已经存在的元素,新添加的集合元素不会覆盖原来已经有的集合元素
HashTable与HashMap的实现原理有什么不同?HashMap基于Hashing原理,是通过put方法和get方法来进行存储和获取元素的,使用put来传递键和值的时候,会先用hashcode方法,计算并返回的hashcode用于找到Map中的bucket位置来存储对象HashMap线程不安全,底层在jdk1.7是数组,链表,在jdk1.8是数组,链表,红黑树HashTable底层是数组,链表,是线程安全的

String方法intern() 你真的会用吗?intern()方法设计的初衷,就是重用String对象,节省内存消耗,这个方法返回的是  返回字符串对象的规范化表示形式,当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用
什么是自动拆装箱?将基本类型用包装器类型包装起来将包装器类型转换为基本类型
String.valueOf和Integer.toString的区别?相同点:都可以用于把int转换成String不同点:String.valueOf可以应用到任何数据类型,且不会有异常报出              Integer.toString先将int转换为Interger型,然后再将Integer转换成String型
三、Java多线程
线程的生命周期包括哪几个阶段?创建,就绪,运行,阻塞,死亡首先是创建,这个时候线程还没有调用start方法,调用了start方法,线程进入就绪状态,还没有获取到CPU的执行指令,获取到了CPU的执行指令也就开始运行了,如果因为一些原因,丢失了CPU执行指令,也就进入了阻塞状态,这个时候必须回到就绪状态,等到重新获得CPU的执行指令,最后状态是死亡状态,线程执行完了,线程结束生命周期
多线程有几种实现方式?继承Thread类,重写Thread的run方法,只可以单继承实现Runnable接口的run方法,并且将Runnable实例传给Thread类,再让Thread类去执行run方法。  


请谈谈什么是进程,什么是线程?进程也就是一个程序从创建,运行,消亡的过程一个进程可以有多个线程,每个线程都有自己的程序计数器,本地方法栈,虚拟机栈
启动线程是用start()方法还是run()方法?用start()方法,开启Start()方法就会自动启动run()方法,这才是多线程。调用run()方法启动的是main底下的run方法,就不是多线程了。
说说线程安全问题,什么实现线程安全,如何实现线程安全?线程安全就是,我们在写的某的某个代码块,比如i++,i初始值为0,第一个线程结果是1,第二个线程为2,这个线程就是安全的,如果线程不安全,那么第一个线程结果是1,第二个线程的结果是1。也就是多个线程执行能够正常执行,不会混乱。可以用synchronized和lock来解决线程安全问题,
sychronized和Lock的区别?sychronized是原子性内置锁,是一个关键字,lock是一个接口自动释放锁,需要手动释放锁,否则就会造成死锁无法判断获取锁的状态,而lock锁可以判断是否获取到了锁lock可以中断等待锁的线程的状态,sychronized里等待的线程会一直等待下去,不能够相应中断sychronized适合锁少量的同步代码,lock适合锁大量的同步代码
sleep()和wait()的区别?两者都可以暂停线程的执行,sleep()方法属于Thread类中的,wait()方法属于Object()类sleep通常用于暂停执行,wait通常用于线程间交互/通信调用sleep(),线程不会释放锁,调用wait(),线程会放弃锁
深入分析ThreadLocal的实现原理?


谈谈对synchronized的偏向锁、轻量级锁、重量级锁的理解?这是锁的优化,锁的状态是由低到高为无锁,偏向锁,轻量级锁,重量级锁。 无锁就是没有锁,偏向锁就是通过对象头的偏向线程ID来对比,轻量级锁就是通过CAS修改对象头锁和自旋来实现的,重量级锁则是除了拥有锁拥有的线程,其他全部都塞。
通过三种方式实现生产者消费者模式?通过一个容器来解决生产者和消费者的强耦合关系,生产者生成数据无需等待消费者索取,消费者无需直接索要数据,通过容器来进行操作。使用synchronize以及wait()、notify()       可以自定义一个阻塞队列,当队列免了的时候,通过wait(),使生产者线程阻塞,并释放队列对象的锁,然后调用notify()方法可以唤醒消费者线程使用lock和Condition的await()和signal()方法
JVM层面分析sychronized如何保证线程安全的?sychronized是原子性内置锁,也被称为监视器锁,我们通过观察被sychronized修饰的编译过后的同步代码块发现,有monitor和monitertesxt字节码指令,执行monitor指令会获取锁,如果获取到了锁,其他竞争锁的线程会进入等待序列,执行了monitortext在字节码指令,锁会释放,处于等待队列中的线程在继续竞争锁
如何写一个线程安全的单例?饿汉式单例模式,在第一次加载时就实例化懒汉式单例模式,在第一次被引用时开始实例化饿汉式比较好
ThreadLocal什么时候会出现OOM的情况?为什么?       1.ThreadLocal是什么?每个线程在对内存中开辟的一块工作内存,同时把线程的共享数据拷贝了一份放进去,相当于做的本地副本,不会像synchronized一样每次修改都要同步到主内存中       2.ThreadLocal有什么用?工作线程的数据交互主要是本地数据和主内存数据的交互,当数据存储在本地内存中,可以大大提高读取效率,避免了线程阻塞造成的cpu的吞吐下降;在多线程中每个线程中都要维护sesion,可以提高对独有资源的工作效率;       3.发生内存泄露原因?synchornized是保证了主内存数据的一致,是时间换空间:通过阻塞一个共享变量,共享一小块内存空间;threadLocal是通过建立线程的副本数据,空间换时间ThreadLocalMap的Key为弱引用,当threadlocal对象被回收(value在ThreadLocalMap调用get、set、remove的时候就会被清除),这时将key设置为null的entry。但是threadlocal一直不会被回收,导致内存的泄露       4.如何避免呢?其实在调用threalocalMap的get/set方法时,会对key=null的entry(threadlocal对象=null)进行回收,也可以在调用结束时调用remove方法进行释放。

为什么wait, notify 和 notifyAll这些方法不在thread类里面?Wait-notify机制是在获取对象锁的前提下不同线程间的通信机制。在Java中,任意对象都可以当作锁来使用,由于锁对象的任意性,所以这些通信方法需要被定义在Object类里。
你真的理解CountDownLatch与CyclicBarrier使用场景吗?CountDownLatch是一个同步的辅助类,允许一个或多个线程,等待其他一组线程完成操作,再继续执行。CyclicBarrier是一个同步的辅助类,允许一组线程相互之间等待,达到一个共同点,再继续执行。
出现死锁,如何排查定位问题?1.在cmd窗口,使用jps指令查询该类的端口号(pid)2.在使用jstack+pid查看日志(jstack pid)
notify和notifyAll的区别?调用notify()方法只随机唤醒一个wait线程,这个线程会从等待池进入锁池,调用notifyAll方法会唤醒所有wait线程,而且会将该对象等待池内的所偶线程移动到锁池种,等待锁竞争。
线程池启动线程submit和execute有什么不同?   execute只能执行Runnable类型的任务,没有返回值   submit可以执行Runnable和Callable类型的任务   submit能获取返回值,并且处理异常,通过捕获Future.get()抛出的异常
SimpleDateFormat是线程安全的吗?如何解决?SinmpleDateFormat是java提供的一个格式化和解析日期的工具类,在java中,可以使用SimpleDateFormat的format方法,将一个Date类型转化成String类型,并且可以指定输出格式。线程不安全,被当作了共享变量在多个线程中进行使用,这就出现了线程安全问题。解决:使用局部变量,就不会被多个线程同时访问到了,避免了线程安全问题           加同步锁,通过加锁使多个线程排队顺序执行           如果是Java8,使用DateTimeFormatter代替SimpleDateFormat
请谈谈ConcurrentHashmap底层实现原理?     ConcurrentHashMap在jdk1.7是分段的数组,链表,在jdk1.8以后是node数组,链表,红黑树。线程是安全的,那怎样实现线程安全的呢?在jdk1.7是分段锁对整个桶数组进行了分割,多线程访问容器里面不同数据段的数据,就不会存在锁竞争,提高了并发访问率。
当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其方法?不可以
线程池的原理,为什么要创建线程池?创建线程池的方式?原理:我们在代码中模拟了10个任务,我们配置的核心线程数是5,等待队列容量为100,所以每次只能存在5个任务同时执行,剩下的5个任务会被放到等待队列中,当前的5个任务中如果有任务被执行完了,线程池就会去拿新的任务执行。池化的思想主要为了减少每次获取资源的消耗,提高对资源的利用率,线程池的好处有降低资源的消耗,提高线程的可管理性。通过构造方法实现,通过Executor框架的工具类Executors来实现。
创建线程池有哪几个核心参数?最大线程数:maxPoolSize核心线程数:corePoolSize任务队列容量:queueCapacity线程空闲时间:keepAliveTime允许核心线程超时 allowCoreThreadTimeout任务拒绝处理器  rejectedExecutionHandler
synchronized修饰的静态方法和非静态方法有什么区别?修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁修饰非静态方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁
四、Java Web什么是Servlet,Servlet生命周期方法?Servlet就是一个接口,主要负责接收浏览器的请求,tomcat服务器调用servlet方法。init()方法  初始化service()方法 运行destory()方法  销毁
什么Session和Cookie,它们之间有什么联系?Session是一个会话,当用户打开浏览器访问一个网站开始,无论在这个网站访问了多少页面,点了多少链接,都属于同一个会话。直到浏览器关闭,都属于同一个会话。Cookie是一种浏览器和服务器交互数据的方式。之间的联系:因为Http协议是无状态的,即每次访问都是相当于一个新的请求,Session和Cookie就解决了这个问题,当客户端向服务端发送了一个请求,服务端收到这个请求就会创建一个Session,随之也会创建一个SeesionID,服务端同时也会创建一个Cookie包含这个SessionID,进行响应给客户端,客户端收到了这个响应,就会设置Cookie信息。接下来客户端每次向同一个网站发送请求时,包含SessionId的cookie信息都会被服务器读取到。
JSP的八个隐含对象有哪些?Request,Response,out 即请求,响应,输出pageContext表示当前页面作用域session 代表当前会话作用域application 代表当前全局作用域config config可以获取一些在web.xml中初始化的参数page:表示当前对象exception:表示异常对象
JSP的四个域对象的作用范围?pagecontext:表示当前页面作用域,有效范围在当前jsp页面里session:表示当前会话作用域,有效作用域就是当前会话application:代表全局作用域,有效范围时应用启动到应用结束request:有效范围就是当前请求周期,从http请求发起,到服务器处理结束,返回响应的整个过程
Post和Get请求的区别?本质都是TCP链接Post比Get安全,例如用户登陆时,如果是Get调用会把账号密码都显示在URL中,而Post调用不会显示Post请求的时候调用的是Service方法后的doPost()方法,Get请求的时候调用的时Service方法后的doGet()方法
转发和重定向有什么区别?请求转发Url的地址不会发生改变,是服务端行为。转发后的页面可以读取上一个页面放在request中的数据。转发请求一次重定向Url的地址会发生改变,是客户端行为。重定向相当于直接在浏览器打开重定向的地址,跟上一个页面没任何关系。重定向至少请求2次
Http1.0和Http1.1的区别是什么?Http1.0默认使用的是短连接,每次请求都要重新建立一次连接。Http1.1默认使用长连接,持续连接有非流水线方式和流水线方式流水线方式是客户在收到HTTP的响应报文之前就能接着发送新的请求报文,非流水线方式是客户在收到一个响应报文以后才能发送下一个请求Http1.1新增了一些错误状态响应码,410表示某个资源被永久性的删除Http1.1提供了更多的缓存控制策略
拦截器与过滤器的区别?1.过滤器依赖servlet容器,拦截器不依赖servlet容器2.过滤器是基于函数回调,拦截器是基于java的反射机制3.拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用4.在action的生命周期里,拦截器可以被多次调用,而Filter只能在容器初始化时调用一次。
五、JVM面试题    JVM内存区域如何划分?基于jdk1.7,线程共享的有程序计数器,虚拟机栈,本地方法栈                   线程私有的有:堆,方法区                  直接内存jdk1.8,      线程共享的有:程序计数器,虚拟机栈,本地方法栈                  线程私有的:堆                  直接内存,元空间

JVM堆中对象是如何创建的?1.类加载检查:若对象对应的类已经经过加载,链接,初始化,则进入下一步。2.分配内存 3.初始化4.设置对象头5.执行init方法
JVM对象的结构?对象头,实例数据,对齐填充
JVM垃圾回收-如何判断对象是否是垃圾对象?1.可达性分析算法,对象到GC root 没有引用链相连,说明是可以回收的2.引用计数法算法,给对象添加一个引用计数器,每当有一个地方引用对象时,计数器加1,当引用失效的时候,引用计数器的值减1,当引用计数器为0,就可以回收
JVM垃圾回收算法有哪些?标记-清除算法标记-复制算法标记-整理算法分代收集算法JVM类的加载器有哪些?启动类加载器,扩展类加载器,应用程序类加载器
JVM垃圾收集器有哪些?新生代有Serial,ParNew,Paraller老年代有Serial Old,Paraller Old,G1,CMS
JVM内存是如何分配的?     计算对象占用的空间大小,在堆中划分内存           1.若堆内存规整(使用标记整理算法进行GC),采用指针碰撞法           2.若堆内存不规整(使用标记清楚算法进行GC会残留下空间碎片),采用空闲列表
从一道面试题分析类的加载过程?加载,链接(验证,准备,解析),初始化,使用,卸载
JVM双亲委派机制?1.如果一个类加载器收到了类加载器请求,他并不贵在即先去加载,而是把这个请求委托给父类的加载器去执行;2.如果父类加载器还存在父类加载器,则进一步向上委托,依次递归,请求最终到达顶层的启动类加载器;3.如果父类加载器可以完成类加载任务,就成功返回,若父类加载器无法完成此加载任务,子加载器才尝试自己去加载。
JVM可以作为GC Root的对象有哪些?1.本地方法栈native方法引用的对象2.栈中引用的对象3.静态变量,常量引用的对象
哪些情况会导致Full GC?老生代无法分配空间,触发FGCSystem.gc
六、SQL性能优化
数据库三范式是什么?数据库的事务、ACID及隔离级别?不考虑事务的隔离性,容易产生哪三种情况?数据库连接池原理?什么是B-Tree?什么是B+Tree?MySQL数据库索引结构?什么是索引?什么条件适合建立索引?什么条件不适合建立索引?索引失效的原因有哪些?如何优化避免索引失效?MySQL如何启动慢查询日志?MySQL如何使用show Profile进行SQL分析?一条执行慢的SQL如何进行优化,如何通过Explain+SQL分析性能?什么是行锁、表锁、读锁、写锁,说说它们各自的特性?什么情况下行锁变表锁?什么情况下会出现间隙锁?谈谈你对MySQL的in和exists用法的理解?MySQL的数据库引擎有哪些,如何确定在项目中要是用的存储引擎?count(*)、count(列名)和count(1)的区别?union和union all的区别?七、Spring框架
Spring的IOC和AOP机制?Spring中Autowired和Resource关键字的区别?依赖注入的方式有几种,各是什么?Spring容器对Bean组件是如何管理的?Spring容器如何创建?Spring事务分类?Spring事务的传播特性?Spring事务的隔离级别?Spring的通知类型有哪些?八、SpringMVC框架
SpringMVC完整工作流程,熟读源码流程?SpringMVC如何处理JSON数据?SpringMVC拦截器原理,如何自定义拦截器?SpringMVC如何将请求映射定位到方法上面?结合源码阐述?SpringMVC常见注解有哪些?SpringMVC容器和Spring容器的区别?SpringMVC的控制器是不是单例模式,如果是,有什么问题,怎么解决?九、MyBatis框架
MyBatis中#和$的区别?#{}是占位符,预编译处理,${}是拼接符,是用来替换字符串的Mybatis在处理#{}的时候,会在预编译的时候把#{}换成?,调用PreparedStatement的set方法来赋值Mybatis在处理${}的时候,会把${}直接替换成变量的值
MyBatis一级缓存原理以及失效情况?缓存就是将用户经常查询到的数据放在缓存中,这样的话,下次用户再次去查询数据就不会去从磁盘上查询,从缓存中查询,提高了查询效率,解决了高并发系统的性能问题一级缓存也叫本地缓存:一级缓存是默认打开的,每个SqlSession实例都拥有一个自己的本地缓存,如果创建一个新的SqlSession实例,则该实例拥有一个新的一级缓存。失效情况:1.SqlSeesion不同                2.SqlSession相同,但查询条件不同                3.SqlSession对象相同,查询条件也相同,但两次查询之间执行了增删改操作                4.使用了ClearCache()方法
MyBatis二级缓存的使用?工作机制:一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中,如果当前会话关闭了,这个会话对应的一级缓存就没了。但是我们想要的是,会话关闭了,一级缓存中的数据就会放在二级缓存中,新的会话查询信息,就会在二级缓冲中获取内容。作用域在Namespace使用步骤:1.让Mybatis框架支持二级缓存                 2.让当前的映射文件支持二级缓存                3.让当前的操作支持二级缓存
MyBatis拦截器原理?Mybatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能。Mybatis允许你在已映射语句执行过程中的某一点进行拦截调用,Mybatis允许使用插件来拦截的方法调用包括:Executor,ParameterHandler,ResultSetHandler,StatementHandler比如在使用分页插件来完成Mybatis分页       分页插件的原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,然后在sql语句添加对应的物理分页语句和物理分页参数。
看过MyBatis源码吗,请说说它的工作流程?1.加载配置文件2.生成SqlSessionFactory工厂3.使用SqlSessionFactory工厂创建SqlSession对象4.使用SqlSession创建Dao接口的代理对象5.使用代理对象执行方法6.关闭SqlSession,释放资源
十、Java高级部分
Dubbo负载均衡策略?Dubbo中Zookeeper做注册中心,如果注册中心集群都挂掉,发布者和订阅者之间还能通信么?Dubbo完整的一次调用链路介绍?请说说SpringBoot自动装配原理?有用过SpringCloud吗,请说说SpringCloud和Dubbo有什么不一样?什么是WebService,如何基于WebService开发接口?谈谈项目中分布式事务应用场景?使用Redis如何实现分布式锁?请谈谈单点登录原理?Tomcat如何优化?后台系统怎么防止请求重复提交?Linux常见命令有哪些?请说说什么是Maven的依赖、继承以及聚合?Git暂存区和工作区的区别?Git如何创建、回退以及撤销版本?

posted @ 2022-03-26 00:32  远乡人  阅读(1223)  评论(0编辑  收藏  举报