阿里面试题 JAVA面试基础

2019-01-29  本文已影响0人  手打丸子

好吧,我确实面过拼多多
标题党主要是想骗你点进来

以下言论既不完整也不精确,概不负责。

我们不仅要知道一门技术的使用方法、实现原理,更要知道为何会有这门技术,第一个想这么搞的人是遇到了什么问题、为了解决什么问题

JAVA基础

面向对象

  1. Java是门面向对象的语言,除了继承、多态这些面向对象时,更该具有面向对象的思维;

    面向对象是模仿现实世界的,现实世界就是一个个对象组件二成,而java构建的虚拟世界,也是一个个对象构建而成;

    随着社会的进步,社会会一点点地分工,而软件也是有生命的,随着软件一点点地“长大”,也需要逐渐地将功能一步步地“分工”出去,这时就需要不断地重构;

    这里举个送快递的例子:刚开始,只需要送一件东西,有个专人从上海送到北京,这时候只有一个对象;后来寄快递的人多了,开始慢慢分化,需要有快递员收集快递,并且有运输员集中运送到北京,再由北京的快递员分发到收件人手中,还会有很多管理人员,有了快递公司(相当于一个专有系统);

  2. 领域模型
    现实世界也会有很多行业,有很多专有的对象,比如演电影的会有灯光师、化妆师、导演等,说出来就知道他是干啥的,可以做点啥,在什么场景和任务下你需要哪些对象;当你的软件是面向某个行业的时候,特别是一些to b的软件,业务场景非常复杂,不再满足于互联网惯用的CRUD贫血模型手法,而应该创建“有形有神”的富血,在团队内部形成统一概念,当拎出一个模型来,说出名字,团队成员都能知道这个对象是做什么的、怎么使用;平时团队内沟通的语言是JAVA语言,在此基础上,我们又拥有了一层领域语言,使各个逻辑构筑与这个领域之上,高屋建瓴,而不是从砖搬起;挂两篇写的不错的资源:阿里盒马领域驱动设计实践领域驱动设计在互联网业务开发中的实践

  3. Spring IOC&AOP
    对于java程序员来说,无人不知无人不用Spring,并且基本都知道Spring IOC和AOP,也都知道实现原理,甚至看过源代码,网上资源也很多,但是说为啥搞这个的不多;既然面向对象是模仿现实世界,也会遇到一样的问题,当你开一家公司,小公司的时候是一个老板带着几个员工干,欢快高效,但是公司一大,对象一多,就很难管理,这是IOC就出现了,起到一个人力资源中心的作用,管理各个对象,并且完成对象的注入;现实世界也有很多SAAS,就是service as a service,一家公司可能需要一点服务,但是不想亲自雇人,只想请人在某个时段参与进来完成某个任务,相当于只想买服务、不想买人,这个时候就产生了AOP,面向切面,你只要告诉我需要“日志服务”之类,我会在各个切入点,完成这个任务,你完全不需要关心是什么对象做了这个动作;Spring IOC & AOP

容器

  1. Collection&Map
    java集合和Map使用频次极高,不仅需要知道有哪些常用的集合和实现,还要知道每个集合类的特性和使用场景,并且需要知道实现原理,翻翻源代码,能从源代码里学到很多。

  2. Collectionc常用:List/Set/Queue;
    List常用:ArrayList/LinkedList
    集合遍历:Iterator
    集合遍历时是否可修改:遍历时不可删元素,用Iterator可以;
    推荐几篇资源:java集合;

  3. 并发包中的集合
    深入浅出ConcurrentHashMap(1.8)
    谈谈ConcurrentHashMap1.7和1.8的不同实现
    ConcurrentHashMap的红黑树实现分析
    深入分析ConcurrentHashMap1.8的扩容实现
    java并发包中的常用类
    并发容器之ConcurrentLinkedQueue

threadlocal

  1. 实现、源代码、使用需要注意的地方;
  2. 使用线程池时,由于线程是重用的,只要线程不被回收,threadLocal变量就不会失效,因此,使用完成变量时,一定要调用remove移除变量;
    比较常用的场景,在spring web中,添加一个filter,每次请求来时,会在业务逻辑开始前查询一些用户信息之类放到threadlocal中,那么,必须在filter的finally中移除threadlocal,否则会导致内存泄漏
  3. threadlocal内部是使用了一个threadlocalMap,每个entry都继承了弱引用,而这个threadlocalMap不是一个真正意义上的map,而是模仿hashmap,采用了hash+数据的结构,不过hash冲突的时候会放到下一个hash槽中,而不是采用链表或者红黑树的形式放到一个hash槽中,这么做是考虑到这个场景下hash冲突概率很小;
  4. 关联知识点:虚引用、软引用、弱引用、强引用
    强引用:就是最普通的引用,有强引用的对象不会被回收;
    软引用:内存够不回收,内存不够回收;很适合用来做缓存类有没有,又缓存又防止内存爆掉;
    弱引用:只有弱引用的对象,是可被回收的;threadlocal正是一个使用场景;
    虚引用:它的get方法一直返回null,由于虚引用的get方法无法拿到真实对象,所以当你不想让真实对象被访问时,可以选择使用虚引用,它唯一能做的是在对象被GC时,收到通知,并执行一些后续工作。;引用不引用压根不影响对象回收,只是个指向,且不能单独使用,必须放到容器中使用;使用场景在DirectByteBuffer中见过,新建DirectByteBuffer的时候会同时生成一个Cleaner用于之后回收直接内存,而这个Cleaner就是虚引用的,并且加入到一个Clean的list还是set中;这么做,大概是因为如果Cleaner已经回收了,表明直接内存也肯定干掉了,用虚引用确实蛮合适;收到回收通知后,会去执行对外内存的释放;
    https://www.jianshu.com/p/7200da8b043f

java线程池

  1. ThreadPoolExecutor的参数,及其意义,任务提交后的运行过程,这里大概提一下;
    参数主要有以下几个:核心线程数、任务阻塞队列、最大线程数、最大线程存活时间、拒绝策略;
    初始化线程池时,一般线程是空的,当然也有策略是预创建好核心线程的,核心线程创建后是不会再被回收的,即使线程处于空闲状态;核心线程无空闲时,新提交的task将被放到阻塞队列中,等核心线程池读取运行;队列也满后(一般都用有界队列,无界队列总感觉心里不踏实),就在最大线程数允许范围内开线程跑,不过一般我都不会用最大线程,因为我一般队列都会搞蛮大,满了就直接拒绝了;最大线程存活时间是用来回收核心线程外的线程的;线程池满了后,就是拒绝策略了,一般我都是打个error日志,线程池爆掉的时候,一般都是系统出问题,立马打error告警是最佳选择;
    线程池的参数量:如果CPU个数为N;如果是cpu密集型,核心线程数使用N+1;如果是IO密集型,需要长时间阻塞等待的,采用2N+1;上面是书上的,实际使用还是靠调出来的,无特殊需求的话也会采用通用策略;比如我们的业务服务器,大部分都是以调用为主,CPU计算做的比较少,在4核8G或者8核16G内存下都开了较大的线程数100-300之间,也能获得不错的性能,不宜开300以上,因为每个线程本身就占300-400K的内存,线程再调大对性能提升也较少了,甚至适得其反;阻塞队列,一般设置个一万问题也不大,全部塞满也就耗几M的内存(这个数据不是很准确,不过确实耗的不大);
    为啥用线程池,重要的一个原因是线程重用,创建销毁一个线程是非常耗资源的,在很多系统中是调用了操作系统创建了轻量级进程;线程池也起到了线程管控的作用,已经限定了线程数量以及处理不过来的时候任务的存放方式等;在pigeon等很多rpc架构中,也用作性能隔离,采用两个线程池fast-pool、slow-pool,检测到某种请求运行很慢时,慢请求放入slow-pool,而正常请求仍旧放在fast-pool中,来保障正常请求的正常运行;netty中会做业务隔离,使用了boss线程池来处理接入请求,而worker线程池来处理其他类请求,通常我们还会加个业务线程池来跑业务逻辑;

  2. ForkJoinPool
    fork-join一般只适用于分而治之的场景,直接使用并不多,除非你是搞算法的;
    这里提到,是因为java8中的并发流以及completablefuture都使用了ForkJoinPool,而并发流写法实在太顺,忍不住就滥用,在无意识的情况下使用到了这个线程池;在不指定线程池的情况下,都使用的ForkJoinPool的默认实现commonPool,一段逻辑阻塞会影响到其他使用了这个并发流的运行,尤其值得注意,需谨记并发流的使用场景;
    ForkJoinPool基于普通线程池,但是提交的任务却存放在线程本地的queue双端队列中,线程运行时先从本地取任务,本地无任务时会从其他线程偷任务运行;
    ForkJoinPool.commonPool核心线程数和cpu等量,明显是个cpu密集型线程池,本人进行了实测,运行高IO阻塞型任务性能极差,所以请谨记不要使用并发流去做非cpu密集型任务;
    这里挂篇学习资源:fork-join-pool

java锁

  1. synchronized内置锁:锁原理、偏向锁、轻量级锁、重量级锁;
    这个资源较多,请自行学习,这里挂两篇不错的资源
    不可不说的java锁事
    深入浅出synchronized

  2. Lock锁
    各种lock较多,核心都是基于AQS;
    挂篇资源吧:深入浅出java同步器AQS

  3. StampedLock
    这个是java8新引入的,不是基于AQS,不过内部实现大同小异,也挂两篇资源
    stampedLock入门
    stampedLock源码分析

  4. volatile
    这个是java中最轻量级的同步,使用volatile修饰的变量,在写入后会加write-barrier(写屏障),在读之前会使用read-barrier(读屏障),这两个屏障,既然

  5. jvm相关
    JVM源码分析之JVM启动流程
    JVM源码分析之堆内存的初始化
    JVM源码分析之Java类的加载过程
    JVM源码分析之Java对象的创建过程
    JVM源码分析之如何触发并执行GC线程
    JVM源码分析之垃圾收集的执行过程
    JVM源码分析之新生代DefNewGeneration的实现
    JVM源码分析之老年代TenuredGeneration的垃圾回收算法实现

  6. 引用
    虚引用:只是指向变量,不持有变量;NIO中的DirectBuffer中之类使用来清理直接内存;只能放在set之类容器中使用,不能单独使用
    弱引用:只有弱引用时,变量可回收;ThreadLocal中的Entry中使用弱引用来保证线程结束时变量可回收;
    强引用:最普通引用;

  7. redis
    https://zhuanlan.zhihu.com/p/31498790

  1. 数据库索引、b+树描述
    数据库,除了增删改查操作,需要理解 数据库事务、索引、数据库锁等概念;
    联合索引啥的,在互联网公司其实用的不多,金融公司会用特别复杂的sql;
    数据库锁:https://zhuanlan.zhihu.com/p/29150809
    数据库事务是通过数据库锁或者快照来实现的
    https://zhuanlan.zhihu.com/p/29166694
    数据库索引:https://www.cnblogs.com/LBSer/p/3322630.html

4.pigeon研究;rpc协议研究对比,特别是thrift
5.spring源码研究
6.java io基础、NIO基础、Netty基础
7.线程估算,怎么确定自己的该用多少线程
8.缓存雪崩的解决方案
9.架构类知识补充;
10.领域模型知识补充
https://juejin.im/entry/5a6555636fb9a01c952633bc
11.线程池研究
12.redis实现分布式锁,考虑主从同步失败:
https://www.jianshu.com/p/fb9993d1b27e
redis运维类知识
13.zookeeper基础、zookeeper的分布式锁一定安全吗?
redis锁的安全性:http://zhangtielei.com/posts/blog-redlock-reasoning-part2.html
上述文章也提到了zookeeper实现分布式锁的不安全性
14.GC的关键技术
https://tech.meituan.com/2016/09/23/g1.html
15.spring
Spring 概述
依赖注入
Spring beans
Spring注解
Spring数据访问
Spring面向切面编程(AOP)
Spring MVC
Spring事务是如何实现的:https://www.ibm.com/developerworks/cn/education/opensource/os-cn-spring-trans/index.html
16.设计模式
https://design-patterns.readthedocs.io/zh_CN/latest/

17.scrum知识复习
18.领域驱动设计书籍
19.netty
https://blog.csdn.net/baiye_xing/article/details/76735113
https://tech.meituan.com/2016/11/04/nio.html
http://www.importnew.com/26258.html
https://blog.csdn.net/baiye_xing/article/details/73351330
20.raft协议
21.算法题:https://www.weiweiblog.cn/13string/
22.分布式事务
23.GC优化:https://tech.meituan.com/2017/12/29/jvm-optimize.html
ZGC:https://juejin.im/entry/5b86a276f265da435c4402d4
24.volatile 内存屏障:http://ifeve.com/memory-barriers-or-fences/
https://in355hz.iteye.com/blog/1797829
25.elasticsearch:倒排索引
26.zookeeper
27.rpc设计
28.unsafe相关的了解:https://tech.meituan.com/2019/02/14/talk-about-java-magic-class-unsafe.html
29.kafka相关
http://www.importnew.com/25247.html
http://trumandu.github.io/2019/04/13/Kafka%E9%9D%A2%E8%AF%95%E9%A2%98%E4%B8%8E%E7%AD%94%E6%A1%88%E5%85%A8%E5%A5%97%E6%95%B4%E7%90%86/

大问题:秒杀场景设计、全局唯一性id设计、内存泄漏问题优化(特别是直接内存泄漏问题)

上机问题:一道简单的算法题(刷leetcode即可)、多线程问题(解决一个问题)

负责的角色:
scrum master、架构师、soa负责人

点餐项目:
容错设计、领域模型设计、培养团队重构能力

排队项目:
缓存设计

https://github.com/Snailclimb/JavaGuide

上一篇下一篇

猜你喜欢

热点阅读