看到标题你可能就知道,我并不是一个像很多网上的文章一样,有一些比如是面试阿里,华为,海康之类大厂的经验,因为实话实说,除了内推,我的简历可能都过不了HR的筛选,很多大厂都说不看学历,我承认,不是每一个大厂的员工学历都很好,但是我敢说大厂的绝大多数员工学历都不错,所以学历是一个门槛,而且慢慢的你会发现,学历可能会是你晋升的基础,创业型的小公司除外,所以如果你现在还是一个在校生,学校也不是很好,考个研也是不错的选择,作为一个再普通不过的一个二本院校毕业的学生深有体会,废话有点多,接下来说一些自己面试过程中面试官问到的问题和怎么和面试官去交流。
总结一下这两天遇到的面试题,个人有个习惯,一般就是面试完之后会记录一下面试官问的问题
Java基础性的问题
- 对JVM的理解,谈谈Java的内存模型,垃圾回收机制,如何确定一个对象是垃圾,一般都知道计数法和可达性分析算法,计数法的话解决不了两个对象互相引用的问题
class A{ public B b; } class B{ public A a; } public class Main{ public static void main(String[] args){ A a = new A(); B b = new B(); a.b=b; b.a=a; } }
还有就是如果是可达性分析算法的话最好能够知道什么样的对象可以作为GCRoots,还有就是垃圾的分代收集算法的具体使用场景,比如新生代,对象频繁创建,对象大多有朝生夕灭的情况,所以采用复制收集或者是升级版的复制整理算法,因为需要拷贝到对象较少,而老年代则不同,大多数经历了多次垃圾回收保留下来的对象。需要回收的相对较少,则可以使用标记清楚算法,这篇文章的主要目的不是去列举一个个的面试问题,然后去一一作答,所以只是粗略的说一下,你知道新生代使用的是复制整理算法,那为什么使用赋值整理算法以及JVM对此的实现有哪些
-
Java基础,集合类,反射(最好能够结合实际开发),集合类的HashMap基本上就是面试的宠儿,最好能列举jdk版本之间的差异性,底层的数据结构,是怎么红黑树化的,这时候你就可以说一下ConcurrentHashMap,如果你了解的话,然后就可以说一下java的并发编程,所有的回答最好都能结合实际的项目经验,在哪个地方有并发,怎么解决的,哪个地方用到了线程池,是用jdk的工具类Executors创建,还是自己手动创建,一般这种时候你就接着说工具类创建的有什么弊端,不要让面试官问你,除非他打断你,要不然你就一直把线程池,有几种线程池的创建方式,你能联想到的都说了,而不是面试官问一个你答一个,这样留个面试官问你的时间相对较少,自然就不会觉得你很多问题答不上来,比如你说到java的线程池,你就最好能举例出几种常见的线程池,比如,固定大小的线程池newFixedThreadPool,只有一个线程的线程池newSingleThreadPool
此时你最好能个说出newFixedThreadPool都需要什么参数,代表什么,比如使用的的队列,队列都有什么性质,简单看一下源码
public static ExecutorService newFixedThreadPool(int var0) {
return new ThreadPoolExecutor(var0, var0, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
}
发现底层还是使用了ThreadPoolExecutor(),这里我们就知道如果我们要自己创建线程池,也需要使用到这个方法,简单看一下的实现
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
corePoolSize:线程池的核心线程数,就是说如果有任务提交,会创建这么多线程,任务完成一般核心线程还会保留,除非手动设置线程回收连核心线程也回收了
maximumPoolSize:所能够接受的最大线程数,就是任务再多,我也处理不过来了,这时就会有线程的一些拒绝策略,具体线程池的拒绝策略有哪些就自己去看吧,这篇文章不是把所有的知识点一一俱到,我也做不到
keepAliveTime:这个参数针对maximumPoolSize,当任务处理完的时候,超过核心线程的线程会被回收,但是不是马上回收,而是在一段时间之后没有任务提交后回收
unit:时间单位,这个没什么好说的
workQueue:工作队列,阻塞队列,这个是重点,比如用于直接交换的SynchronousQueue,无界队列LinkedBlockingQueue,有界队列ArrayBlockIngQueue等等,以及他们都使用在哪些地方,我们可以从上面的源码中看到newFixedThreadPool底层用的LinkedBlockingQueue,超时时间是0,而newSingleThreadExecutor只有一个线程的方法和他唯一不同的就只有核心线程数corePoolSize是1,最大线程数maximumPoolSize也是1
public static ExecutorService newSingleThreadExecutor() {
return new Executors.FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()));
}
3.解决Java并发时使用的锁和关键字,不加锁也能实现线程安全的ThreadLocal的使用场景和底层实现,Thread,ThreadLocalMaps,ThreadLocal之间的关系,ThreadLocal的初始化方式都有哪些,ThreadLocal为什么会有OOM问题,这个地方的话就会有Java对象引用的具体内容,强引用,弱引用,虚引用等,这个我就不一一列举了,只能说很重要
4.算法,数据结构,数据库一样都是很重要的知识
5.使用到的中间件,比如消息队列RabbitMQ,Kafka,Redis也可以但是不推荐,怎么实现消息的100%可靠传输(消息落库,定时重传),为什么使用这个消息队列,而没有使用另一个,这里需要知道之间的差异,专人干转赚事,elasticsearch的使用,权限认证系统的大致流程,等等这些每个人项目使用的中间件不一样就不一一说了,持续化集成部署有没有了解,Jenkins,docker,k8s了不了解,有没有使用过等等
最后总结一句话,知识全靠日常积累。