当前位置: 首页 > 后端技术 > Java

Java1面试常见问题(中)

时间:2023-04-01 23:01:27 Java

Java1面试常见问题(中)SQL语句优化有哪些?如何优化数据库优化?优化查询,尽量避免全表扫描,首先考虑在where和orderby涉及的列上建索引。尽量避免在where子句中判断字段的空值,否则引擎会放弃使用索引,进行全表扫描。应该尽量避免在where子句中使用!=或<>运算符,否则引擎会放弃使用索引而进行全表扫描。乐观锁和悲观锁及其应用场景详解悲观锁(PessimisticLock),顾名思义,就是非常悲观。你每次去拿数据,你都以为别人会修改它,所以你每次拿数据都会加锁,所以别人要拿这个数据,就一直阻塞,直到拿到锁。传统关系型数据库中使用了很多这样的锁机制,比如行锁、表锁等,读锁、写锁等,都是在操作执行前加锁。乐观锁(OptimisticLock),顾名思义,就是非常乐观。每次去拿数据,我都以为别人不会修改,所以不会加锁,但是更新的时候,我会判断这段时间别人有没有更新过。数据,可以使用版本号等机制。乐观锁适用于多读应用类型,可以提高吞吐量。比如数据库如果提供类似write_condition的机制,其实就是乐观锁。使用场景:两种锁具各有优缺点,不能说哪一种好。乐观锁适用于写操作比较少的情况,也就是真正很少发生冲突的情况,可以节省需要锁的开销,提高系统的整体吞吐量。但是,如果频繁发生冲突,上层应用会不断重试,实际上会降低性能,所以悲观锁在这种情况下更合适。过滤器和拦截器的区别以及如何在项目中应用过滤器:在目标资源之前执行的操作,过滤所有内容,例如action、servlet、jsp、html拦截器:在目标资源之前执行的操作,不能拦截所有内容,阻塞action,可以不能拦截jsp,不能拦截html拦截器和过滤器有很多相似之处,但两者有根本的区别。主要区别如下:(1)拦截器基于JAVA反射机制,而过滤器基于函数回调。(2)拦截器不依赖于Servlet容器,而过滤器依赖于Servlet容器。(3)拦截器只能作用于Action请求,而过滤器几乎可以作用于所有请求。(4)拦截器可以访问Action上下文和值栈中的对象,而过滤器不能。(5)在Action的生命周期中,拦截器可以被调用多次,而过滤器只能在容器初始化时被调用一次。GC回收机制原理在用户的Java程序运行过程中,Java虚拟机提供了另外一个系统级线程,负责回收不再使用的对象占用的内存。这个过程称为垃圾收集。垃圾回收需要对堆内存中的对象进行标记,并对堆内存进行组织。这个过程的某些阶段需要用户Java线程暂时终止,并在回收完成后恢复执行。因此,频繁触发虚拟机垃圾回收操作的行为会影响程序的运行效率。那么在什么情况下会频繁触发垃圾回收操作,比如:堆内存设置太小,再比如:程序频繁分配大的本地对象数组。ConcurrentHashMap原理JDK1.7(Segment数组结构和HashEntry数组结构)JDK1.7ConcurrentHashMap由Segment数组结构和HashEntry数组结构组成。每个segment对应一个Hash表,有独立的锁,所以每个线程访问一个segment,可以并行访问,从而提高效率。这就是锁分段。(1)先将数据分成段,逐段存储,然后为每一段数据分配锁。当一个线程占用锁访问一段数据时,其他段的数据也可以被其他线程访问。(2)Segment实现了ReentrantLock,所以Segment是一个起到锁作用的可重入锁。HashEntry用于存储键值对数据。(3)一个ConcurrentHashMap包含多个Segment数组。Segment的结构类似于HashMap,是数组和链表结构。一个Segment包含一个HashEntry数组,每个HashEntry都是一个链表结构的元素。每个Segment保护HashEntry数组中的元素。在修改HashEntry数组的数据时,先获取对应Segment的锁。(4)Parallelism(默认16)concurrencyLevel:并行级别,并发数,段数,怎么翻译不重要,看懂就好。默认为16,即ConcurrentHashMap有16个Segment,最多可支持16个线程同时并发写入。JDK1.8(数组+链表+红黑树)(1)ConcurrentHashMap取消了Segment段锁,使用CAS和synchronized保证并发安全。(2)数据结构类似于HashMap1.8的结构,数组+链表/红黑树。(3)当链表长度超过一定阈值(8)时,jdk1.8将链表(寻址时间复杂度O(N))转为红黑树(寻址时间复杂度O(log(N))))(4)synchronized只锁当前链表或红黑树的首节点,所以只要hash不冲突,就不会并发,效率会提高N倍。