技术篇
1.什么是快速失败(fail-fast)什么是安全失败(fail-safe)?
我们都接触 HashMap、ArrayList 这些集合类,这些在 java.util 包的集合类就都是快速失败的;而 java.util.concurrent 包下的类都是安全失败,比如:ConcurrentHashMap。
一:快速失败(fail—fast)
如果 A 线程正在对集合进行遍历,此时 B 线程对集合进行修改(增加、删除、修改),或者 A 线程在遍历过程中对集合进行修改,都会导致 A 线程抛出 ConcurrentModificationException 异常。所以不能进行修改!
原理:迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果内容发生变化,就会改变modCount的值。每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值,是的话就返回遍历;否则抛出异常,终止遍历。
注意:这里异常的抛出条件是检测到 modCount!=expectedmodCount 这个条件。如果集合发生变化时修改modCount值刚好又设置为了expectedmodCount值,则异常不会抛出。因此,不能依赖于这个异常是否抛出而进行并发操作的编程,这个异常只建议用于检测并发修改的bug。
场景:java.util包下的集合类都是快速失败的,不能在多线程下发生并发修改(迭代过程中被修改)。
二:安全失败(fail—safe)
java.util.concurrent包下的容器都是安全失败,采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。
原理:由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,所以不会触发Concurrent Modification Exception。
缺点:基于拷贝内容的优点是避免了Concurrent Modification Exception,但同样地,迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的。
场景:java.util.concurrent包下的容器都是安全失败,可以在多线程下并发使用,并发修改。
2.jvm最大内存限制
一般来说,如果再不考虑用java -Xmx参数作为调整得话,jvm最大内存限制是由jdk版本,物理内存,操作系统决定的。
3.线程池的运行流程,参数,拒绝策略
一般线程池是包括六个参数的,分别是new ThreadPoolExcutor(corePollsize,maximumPollsize,keepAliveTime,unit,WorkQueue queue,ThreadFactor threadFactor,RejectHander rejectHander)
-corePollsize :核心线程数
-maximumPoolsize:最大的线程数
-keepAliveTIme:空闲线程最多等待时长会被回收
-unit时间单位
-threadFactor 创建线程的工厂
-rejectHander:拒绝策略
线程池的运行流程:当向线程池中使用对象时,判断线程池中线程数是否超过核心线程数,若超过则加入工作队列,如果核心队列已满,则判断线程数是否大于最大先程数,如果小于,创建新线程,如果大于,则拒绝。
4.StringBuffer和StringBuild的区别
StringBuffer是线程安全的,StringBuild是线程不安全的,底层实现是因为StringBuffer关键函数由Synchronized修饰
非技术篇
1.说一下你的实习经历,以及实习过程做了什么?
2.介绍一下自己的性格特点?