Java面试题总结

分布式事务解决方案

 

线程池java

 

分布式锁mysql

 

Spring IOC和AOP程序员

 

Spring BeanFactory 算法

 

Jvm原理和垃圾回收机制sql

 

Spring事务的1+3种实现方式、7种传播行为、4种隔离级别数据库

1)编程式事务管理:调用beginTransaction()、commit()、rollback()等事务管理相关的方法 
2)声明式事务管理:基于TransactionProxyFactoryBean的声明式事务管理:–不多使用 
3)声明式事务管理:基于AspectAOP声明式事务管理:–常使用 
4)声明式事务管理:基于注解@Transaction的声明式事务管理:–常用
1)propagation_requierd:若是当前没有事务,就新建一个事务,若是已存在一个事务中,加入到这个事务中,这是最多见的选择。Spring默认的事务传播行为 
2)propagation_supports:支持当前事务,若是没有当前事务,就以非事务方法执行。 
3)propagation_mandatory:使用当前事务,若是没有当前事务,就抛出异常。 
4)propagation_required_new:新建事务,若是当前事务存在,把当前事务挂起。 
5)propagation_not_supported:以非事务方式执行操做,若是当前存在事务,就把当前事务挂起。 
6)propagation_never:以非事务方式执行操做,若是当前事务存在则抛出异常。 
7)propagation_nested:若是当前存在事务,则在嵌套事务内执行。若是当前没有事务,则执行与propagation_required相似的操做。 
注:Spring事务的嵌套解析—-Spring的事务传播策略在内部方法调用时将不起做用
Spring的事务传播策略在两个不一样的Service调用时会起做用 
class ServiceA { 
void methodA() {ServiceB.methodB();} 
class ServiceB { 
void methodB() {… } 
若是ServiceA.methodA已经起了事务,调用ServiceB.methodB时,B不新起事务,若是A没有事务,则B新建一个事务,B回滚A也回滚。
1)读未提交:T1读取T2未提交的东西,会出现脏读,不可重复读,幻读 
2)读已提交:mysql默认,会出现不可重复读和幻读 
3)可重复读:针对的是update操做,可是会出现幻读现象,幻读针对的是insert操做 
4)串行化:解决了脏读、不可重复读和幻读,可是效率比较低

Spring Bean的生命周期 编程

    一、实例化一个Bean--也就是咱们常说的new;后端

    二、按照Spring上下文对实例化的Bean进行配置--也就是IOC注入;数组

    三、若是这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id值缓存

    四、若是这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(setBeanFactory(BeanFactory)传递的是Spring工厂自身(能够用这个方式来获取其它Bean,只需在Spring配置文件中配置一个普通的Bean就能够);

    五、若是这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文(一样这个方式也能够实现步骤4的内容,但比4更好,由于ApplicationContext是BeanFactory的子接口,有更多的实现方法);

    六、若是这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor常常被用做是Bean内容的更改,而且因为这个是在Bean初始化结束时调用那个的方法,也能够被应用于内存或缓存技术;

    七、若是Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法。

    八、若是这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法、;

    注:以上工做完成之后就能够应用这个Bean了,那这个Bean是一个Singleton的,因此通常状况下咱们调用同一个id的Bean会是在内容地址相同的实例,固然在Spring配置文件中也能够配置非Singleton,这里咱们不作赘述。

    九、当Bean再也不须要时,会通过清理阶段,若是Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法;

    十、最后,若是这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法

 

事务的ACID是指什么

原子性 (atomicity):强调事务的不可分割.
一致性 (consistency):事务的执行的先后数据的完整性保持一致.
隔离性 (isolation):一个事务执行的过程当中,不该该受到其余事务的干扰
持久性(durability) :事务一旦结束,数据就持久到数据库

事务隔离级别?
DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别
未提交读(read uncommited) :脏读,不可重复读,虚读都有可能发生
已提交读 (read commited):避免脏读。可是不可重复读和虚读有可能发生
可重复读 (repeatable read) :避免脏读和不可重复读.可是虚读有可能发生
串行化的 (serializable) :避免以上全部读问题

事务传播机制?
保证同一个事务中
PROPAGATION_REQUIRED 支持当前事务,若是不存在 就新建一个(默认)
PROPAGATION_SUPPORTS 支持当前事务,若是不存在,就不使用事务
PROPAGATION_MANDATORY 支持当前事务,若是不存在,抛出异常
保证没有在同一个事务中
PROPAGATION_REQUIRES_NEW 若是有事务存在,挂起当前事务,建立一个新的事务
PROPAGATION_NOT_SUPPORTED 以非事务方式运行,若是有事务存在,挂起当前事务
PROPAGATION_NEVER 以非事务方式运行,若是有事务存在,抛出异常
PROPAGATION_NESTED 若是当前事务存在,则嵌套事务执行

抽象类和接口的区别

a.一个类只能继承单个类,可是能够实现多个接口

b.抽象类中能够有构造方法,接口中不能有构造方法

c.抽象类中的全部方法并不必定要是抽象的,你能够选择在抽象类中实现一些基本的方法。而接口要求全部的方法都必须是抽象的

d.抽象类中能够包含静态方法,接口中不能够

e.抽象类中能够有普通成员变量,接口中不能够

 

访问修饰符public,private,protected,以及不写(默认)时的区别?

修饰符 当前类 同 包 子 类 其余包
public
protected ×
default × ×
private × × ×

String和StringBuilder、StringBuffer的区别?

 String和StringBuffer/StringBuilder,它们能够储存和操做字符串。其中String是只读字符串,也就意味着String引用的字符串内容是不能被改变的。

而StringBuffer/StringBuilder类表示的字符串对象能够直接进行修改。StringBuilder是Java 5中引入的,它和StringBuffer的方法彻底相同,区别在于它是在单线程环境下使用的,由于它的全部方面都没有被synchronized修饰,所以它的效率也比StringBuffer要高

 

String a = "str"; String b = new String("str");问 a == b , a.equals(b) 的值是true仍是false?
==:比较引用类型比较的是地址值是否相同
equals:比较引用类型默认也是比较地址值是否相同,而String类重写了equals()方法,比较的是内容是否相同
String a = "str"; ,"str" 存到方法区的字符串常量池。而String b = new String("str");,new String() 存到堆中,在指向常量池的"str"。
用 == 时,a指向的是字符串常量池地址,而b指向的是 new String() 堆中存放地址。因此必然false。而String 的equals 是比较内容。因此是 true

Java 中的final关键字有哪些用法?

(1)修饰类:表示该类不能被继承

(2)修饰方法:表示方法不能被重写

(3)修饰变量:表示变量只能一次赋值之后值不能被修改(常量)

 

阐述final、finally、finalize的区别

- final:修饰符(关键字)有三种用法:若是一个类被声明为final,意味着它不能再派生出新的子类,即不能被继承,所以它和abstract是反义词。将变量声明为final,能够保证它们在使用中不被改变,被声明为final的变量必须在声明时给定初值,而在之后的引用中只能读取不可修改。被声明为final的方法也一样只能使用,不能在子类中被重写。
- finally:一般放在try…catch…的后面构造老是执行代码块,这就意味着程序不管正常执行仍是发生异常,这里的代码只要JVM不关闭都能执行,能够将释放外部资源的代码写在finally块中。
- finalize:Object类中定义的方法,Java中容许使用finalize()方法在垃圾收集器将对象从内存中清除出去以前作必要的清理工做。这个方法是由垃圾收集器在销毁对象时调用的,经过重写finalize()方法能够整理系统资源或者执行其余清理工做。

 

启动一个线程是调用run()仍是start()方法?

 启动一个线程是调用start()方法,使线程所表明的虚拟处理机处于可运行状态,这意味着它能够由JVM 调度并执行,这并不意味着线程就会当即运行。run()方法是线程启动后要进行回调(callback)的方法。

 

简述synchronized 和java.util.concurrent.locks.Lock的异同

Lock是Java 5之后引入的新的API,和关键字synchronized相比

主要相同点:Lock 能完成synchronized所实现的全部功能;

主要不一样点:Lock有比synchronized更精确的线程语义和更好的性能,并且不强制性的要求必定要得到锁。synchronized会自动释放锁,而Lock必定要求程序员手工释放,而且最好在finally 块中释放(这是释放外部资源的最好的地方)

 

mysql存储引擎的 InnoDB 与 MyISAM区别 

1)InnoDB支持事务,MyISAM不支持,这一点是很是之重要。事务是一种高级的处理方式,如在一些列增删改中只要哪一个出错还能够回滚还原,而MyISAM就不能够了。
 
2)MyISAM适合查询以及插入为主的应用,InnoDB适合频繁修改以及涉及到安全性较高的应用
 
3)InnoDB支持外键,MyISAM不支持
 
4)从MySQL5.5.5之后,InnoDB是默认引擎
 
5) Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高
 
6)InnoDB中不保存表的行数,如select count() from table时,InnoDB须要扫描一遍整个表来计算有多少行,可是MyISAM只要简单的读出保存好的行数便可。注意的是,当count()语句包含where条件时MyISAM也须要扫描整个表
 
7)对于自增加的字段,InnoDB中必须包含只有该字段的索引,可是在MyISAM表中能够和其余字段一块儿创建联合索引
 
8)清空整个表时,InnoDB是一行一行的删除,效率很是慢。MyISAM则会重建表
 
9) 锁机制不一样: InnoDB 为行级锁,MyISAM 为表级锁
注意:当数据库没法肯定,所找的行时,也会变为锁定整个表。 
如: update table set num = 10 where username like “%test%”; 

 

 

Spring MVC 运行流程

 

 
1.用户发送请求到DispatchServlet
 
2.DispatchServlet根据请求路径查询具体的Handler
 
3.HandlerMapping返回一个HandlerExcutionChain给DispatchServlet
 
HandlerExcutionChain:Handler和Interceptor集合
 
4.DispatchServlet调用HandlerAdapter适配器
 
5.HandlerAdapter调用具体的Handler处理业务
 
6.Handler处理结束返回一个具体的ModelAndView给适配器
 
ModelAndView:model–>数据模型,view–>视图名称
 
7.适配器将ModelAndView给DispatchServlet
 
8.DispatchServlet把视图名称给ViewResolver视图解析器
 
9.ViewResolver返回一个具体的视图给DispatchServlet
 
10.渲染视图
 
11.展现给用户
 

 Redis所支持的数据结构

String(字符串)、List(列表)、Set(集合)、Zset(有序集合)、Hash(哈希)

 

Nginx实现负载均衡的方法有哪些

轮询(默认)——每一个请求按时间顺序逐一分配到不一样的后端服务器,若是后端服务器down掉,能自动剔除。

weight ——指定轮询概率,weight和访问比率成正比,用于后端服务器性能不均的状况。

ip_hash ——每一个请求按访问ip的hash结果分配,这样每一个访客固定访问一个后端服务器。

backup——其它全部的非backup机器down或者忙的时候,请求backup机器。因此这台机器压力会最轻。

down——表示单前的server暂时不参与负载

fair(第三方)按后端服务器的响应时间来分配请求,响应时间短的优先分配。与weight分配策略相似。

HashMap、HashTable、ConcurrentHashMap的区别

 

HashTable

 

  • 底层数组+链表实现,不管key仍是value都不能为null,线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低,ConcurrentHashMap作了相关优化
  • 初始size为11,扩容:newsize = olesize*2+1
  • 计算index的方法:index = (hash & 0x7FFFFFFF) % tab.length

HashMap

  • 底层数组+链表实现,可以存储null键和null值,线程不安全
  • 初始size为16,扩容:newsize = oldsize*2,size必定为2的n次幂
  • 扩容针对整个Map,每次扩容时,原来数组中的元素依次从新计算存放位置,并从新插入
  • 插入元素后才判断该不应扩容,有可能无效扩容(插入后若是扩容,若是没有再次插入,就会产生无效扩容)
  • 当Map中元素总数超过Entry数组的75%,触发扩容操做,为了减小链表长度,元素分配更均匀
  • 计算index方法:index = hash & (tab.length – 1)

 

HashMap的初始值还要考虑加载因子:

  •  哈希冲突:若干Key的哈希值按数组大小取模后,若是落在同一个数组下标上,将组成一条Entry链,对Key的查找须要遍历Entry链上的每一个元素执行equals()比较。
  • 加载因子:为了下降哈希冲突的几率,默认当HashMap中的键值对达到数组大小的75%时,即会触发扩容。所以,若是预估容量是100,即须要设定100/0.75=134的数组大小。
  • 空间换时间:若是但愿加快Key查找的时间,还能够进一步下降加载因子,加大初始大小,以下降哈希冲突的几率。

HashMap和Hashtable都是用hash算法来决定其元素的存储,所以HashMap和Hashtable的hash表包含以下属性:

  • 容量(capacity):hash表中桶的数量
  • 初始化容量(initial capacity):建立hash表时桶的数量,HashMap容许在构造器中指定初始化容量
  • 尺寸(size):当前hash表中记录的数量
  • 负载因子(load factor):负载因子等于“size/capacity”。负载因子为0,表示空的hash表,0.5表示半满的散列表,依此类推。轻负载的散列表具备冲突少、适宜插入与查询的特色(可是使用Iterator迭代元素时比较慢)

除此以外,hash表里还有一个“负载极限”,“负载极限”是一个0~1的数值,“负载极限”决定了hash表的最大填满程度。当hash表中的负载因子达到指定的“负载极限”时,hash表会自动成倍地增长容量(桶的数量),并将原有的对象从新分配,放入新的桶内,这称为rehashing。

HashMap和Hashtable的构造器容许指定一个负载极限,HashMap和Hashtable默认的“负载极限”为0.75,这代表当该hash表的3/4已经被填满时,hash表会发生rehashing。

“负载极限”的默认值(0.75)是时间和空间成本上的一种折中:

  • 较高的“负载极限”能够下降hash表所占用的内存空间,但会增长查询数据的时间开销,而查询是最频繁的操做(HashMap的get()与put()方法都要用到查询)
  • 较低的“负载极限”会提升查询数据的性能,但会增长hash表所占用的内存开销

程序猿能够根据实际状况来调整“负载极限”值。

ConcurrentHashMap

  • 底层采用分段的数组+链表实现,线程安全
  • 经过把整个Map分为N个Segment,能够提供相同的线程安全,可是效率提高N倍,默认提高16倍。(读操做不加锁,因为HashEntry的value变量是 volatile的,也能保证读取到最新的值。)
  • Hashtable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap容许多个修改操做并发进行,其关键在于使用了锁分离技术
  • 有些方法须要跨段,好比size()和containsValue(),它们可能须要锁定整个表而而不只仅是某个段,这须要按顺序锁定全部段,操做完毕后,又按顺序释放全部段的锁
  • 扩容:段内扩容(段内元素超过该段对应Entry数组长度的75%触发扩容,不会对整个Map进行扩容),插入前检测需不须要扩容,有效避免无效扩容

 

Lock和synchronized的区别

Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;

synchronized在发生异常时,会自动释放线程占有的锁,所以不会致使死锁现象发生;而Lock在发生异常时,若是没有主动经过unLock()去释放锁,则极可能形成死锁现象,所以使用Lock时须要在finally块中释放锁;

Lock可让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不可以响应中断;

经过Lock能够知道有没有成功获取锁,而synchronized却没法办到。

Lock能够提升多个线程进行读操做的效率。

 ThreadLocal的原理做用

 

并发编程之ThreadLocal、Volatile、Synchronized、Atomic关键字比较 

相关文章
相关标签/搜索