java面试总结

1.有没有有顺序的Map实现类,若是有,他们是怎么保证有序的? 

TreeMap和LinkedHashmap都是有序的。(TreeMap默认是key升序(字典排序)),LinkedHashmap默认是数据插入顺序)java

TreeMap是基于比较器Comparator来实现有序的(内部结构为红黑树)。mysql

LinkedHashmap是基于链表来实现数据插入有序的。react

 

2.HashMap何时扩容,每次扩容多少,为何?

扩容时机:容量达到当前最大容器 *  负载因子(初始默认容量16,负载因子0.75)nginx

扩容大小:每次扩容一倍面试

为何扩容一倍:1.容量为2的n次方时,能够减小hash碰撞     2.计算位置时经过位运算,而不是取模可使效率提升,源码以下:redis

e.hash & (newCap - 1)

 

3.JAVA8的ConcurrentHashMap为何放弃了分段锁,有什么问题吗?JAVA8怎么处理的?

问题:算法

    1.加入多个分段锁浪费内存空间spring

    2.生产环境中, map 在放入时竞争同一个锁的几率很是小,分段锁反而会形成更新等操做的长时间等待。sql

    3.为了提升 GC 的效率数据库

java8处理:

   采用CAS+volatile 来代替锁保证原子性,不过其中部分代码段仍是加上了Synchronized(说明Synchroniezd的效率已经高于Lock锁了)。

 

4.IO模型有哪些,讲讲你理解的nio ,他和bio,aio的区别是啥,谈谈reactor模型。

JAVA BIO:同步并阻塞,服务器实现模式为一个链接一个线程,即客户端有链接请求时服务器端就须要启动一个线程并处理,若是这个链接不作任何事情会形成没必要要的开销,固然能够经过线程池机制改善。
JAVA NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的链接请求都会注册到多路复用器上,多路复用器轮询到链接有IO请求时才启动一个线程进行处理。
JAVA AIO(NIO2):异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。

reactor模型自行百度。

 

5.反射的原理,反射建立类实例的三种方式是什么

反射机制指的是程序在运行时可以动态获取自身的信息。在java中,只要给定类的名字,  那么就能够经过反射机制来得到类的全部信息。

反射机制获取class的方法:

   1使用 Class.forName :Class1=Class.forName("user")

   2.使用类的 .class 方法:Class2=User.class   //每一个类型都有class属性

  3.使用类对象的 getClass() 方法:User user=new User();     Class3=user.getClass()     //每一个Java对象都有getClass方法。

反射建立对象的两种方式:

     1.调用默认构造函数(无参):

                         Class<?> forName=Class.forName("com.test.entity.user");

                         Object  newInstance=forName.newInstance();

    2.调用有带参数的构造函数的类,先获取到其构造对象,再经过该构造方法类获取实例:

                       Class<?> forName=Class.forName("com.test.entity.user");

                       Constructor<?>  constructor=forName.getConstructor(String.class,String.class);   ///获取构造函数类的对象

                       User  user=(User)constructor.newInstance("test","test");
 

 

6.反射中,Class.forName和ClassLoader区别 

    在java中Class.forName()和ClassLoader均可以对类进行加载。ClassLoader就是遵循双亲委派模型最终调用启动类加载器的类加载器,实现的功能是“经过一个类的全限定名来获取描述此类的二进制字节流”,获取到二进制流后放到JVM中。Class.forName()方法实际上也是调用的CLassLoader来实现的。不过Class.forName加载类时将类进了初始化,而ClassLoader的loadClass并无对类进行初始化,只是把类加载到了虚拟机中。

 

7.动态代理与cglib实现的区别

    java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

    cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,经过修改其字节码生成子类来处理。

 

8.java8的经常使用新特性

     lambda表达式          stream流(推荐使用,在对集合的数据处理时,使用特别方便)

 

9.jvm相关

     内存结构 :  堆  元空间(方法区)    java虚拟机栈   本地方法栈   程序计数器

     内存模型 :  主内存 ,工做内存(本地内存) 等概念。

     怎么判断对象(引用)是否存活:  引用计数法(淘汰---不能解决循环依赖)  , 根搜索算法(可达性分析算法)

     经常使用垃圾回收算法 :标记清除(老年代,产生大量内存碎片,效率不高),标记整理(老年代),复制算法(新生带)

     一次完整的GC流程分析

     java类加载机制--双亲委派模型(如何打破双亲委派模型--- 自定义类加载器重写loadClass方法;使用线程上下文类加载器)

    垃圾收集器: 掌握cms  g1便可。(常问cms和g1的阶段以及stw发生在那些阶段, g1的筛选回收为何回收的时间可让用户                             设定。)

    另外能够了解下: 逃逸分析,本地线程分配缓冲,空间分配担保机制,动态年龄判断等概念。

 

 

10.多线程方面 

   怎么建立线程---继承Thread   实现Runnable 或者Callable  ,线程池

   线程池的流程,核心参数(几乎必问)---为何使用newCachedThreadPool这些线程池建立线程会发生内存溢出?

    怎么关闭线程池:

              shutdown()调用后,不能够再 submit 新的 task,已经 submit 的将继续执行
     shutdownNow()调用后,试图中止当前正在执行的 task,并返回还没有执行的 task 的 list

   ThreadLocal的原理分析(几乎必问)-- 注意不使用时须要remove,否则会形成内存泄漏

   Synchronized的底层实现原理以及锁的升级 参考这篇文章(真的不错 ):

                                         http://www.noobyard.com/article/p-ykqidgav-ea.html

  volatile的做用:保证线程见的可见性,禁止重排序(实现原理--直接读写主内存)

  CAS的实现原理,如何解决ABA问题

  线程死锁的解决方式 : 长时间获取不到锁,放弃操做而且释放本身占有的锁;一次性申请所需的锁资源,按必定顺序申请锁资    源。

原子类的实现原理 --CAS

countdowlatch和cyclicbarrier的内部原理和用法,以及相互之间的差异:countdownlatch表示线程到达一个点把一个变量减一,子线程并不会阻塞,继续运行,主要就是countDown和await两个方法,调用await方法的线程被阻塞直到变量减到0,cyclibarrier表示线程到达一个点后,阻塞当前线程直到这组线程的其余线程也到达这个点。

countdowlatch 不能重复使用,一次能够唤醒多个线程 ; cyclibarrier能够重复使用,一次只能唤醒一个线程。

 

 

11.spring框架相关问题

     一个接口被多个类实现,怎么注入:@Resource      @Qualifier+@Autowired

    springmvc的处理流程 

    AOP概念,实现原理: 动态代理(@Aspect注解实现,了解其中的通知类型--前置通知,环绕通知,后置通知,异常通知,        最终通知)

   spring事务的传播机(七种),数据库隔离级别(4种)

    spring事务@transactional失效的缘由:         

             1.数据库引擎是否支持事务(Mysql的MyIsam引擎就不支持事务)

             2.注解所在的类是否注入spring容器中

             3.注解所在方法是否为public修饰

             4.所用数据源是否加载了事务管理器

             5.是否发生了方法的自调用(同一个类中的A方法调用B方法)

             6.当方法发生异常时,使用try catch捕获了异常,而且catch中没有抛出异常或者手动回滚。

     

 spring bean的生命周期。

 

12.数据库相关

mysql和orcale的分页查询 :  mysql:limit        orcale: rownum

索引的分类:普通索引,惟一索引,主键索引,全文索引,组合索引

索引的实现原理:B+树

怎么对数据库进行优化:表结构优化,sql语句优化

怎么对sql语句进行分析: explain(执行计划)

数据库乐观锁,悲观锁实现:乐观锁:版本号          悲观锁:共享锁(LOCK IN SHARE MODE)  排他锁(FOR UPDATE)

数据库中的脏读,重复读,幻读对应的解决隔离级别

mysql中in 和exists 区别

    1.IN查询在内部表和外部表上均可以使用到索引。
    2.Exists查询仅在内部表上可使用到索引。
    3.当子查询结果集很大,而外部表较小的时候,Exists的Block Nested Loop(Block 嵌套循环)的做用开始显现,并弥补外部表没法用到索引的缺陷,查询效率会优于IN。
    4.当子查询结果集较小,而外部表很大的时候,Exists的Block嵌套循环优化效果不明显,IN 的外表索引优点占主要做用,此时IN的查询效率会优于Exists。
    5.表的规模不是看内部表和外部表,而是外部表和子查询结果集。

 

 

13.redis相关

   redis中的数据结构 :string  list   hash  set   zset

   redis中键的淘汰策略:

          noeviction: 不删除策略, 达到最大内存限制时, 若是须要更多内存, 直接返回错误信息。 大多数写命令都会致使占用更多的内存(有极少数会例外, 如 DEL )。
          allkeys-lru: 全部key通用; 优先删除最近最少使用(less recently used ,LRU) 的 key。
          volatile-lru: 只限于设置了 expire 的部分; 优先删除最近最少使用(less recently used ,LRU) 的 key。
          allkeys-random: 全部key通用; 随机删除一部分 key。
          volatile-random: 只限于设置了 expire 的部分; 随机删除一部分 key。
          volatile-ttl: 只限于设置了 expire 的部分; 优先删除剩余时间(time to live,TTL) 短的key。

redis持久化机制: 

       aof:实时对数据进行持久化,效率不高,AOF文件比RDB文件大,且恢复速度慢。

       rdb:m时间n个key发生了改变才对数据进行一次记录,采用单独的子进程进行持久化。只有一个文件dump.rdb,方便持久     化。

redis内存设置: maxmemory

redis实现分布式锁:先拿setnx来争抢锁,抢到以后,再用expire给锁加一个过时时间防止锁忘记了释放。

redis缓存穿透解决方案:

    1.查询数据库没有找到值的时候,直接返回null,而后将null或者特定的字符写入redis缓存中。缓存有效时间能够设置短点,如30秒(设置太长会致使正常状况也无法使用)。

    2.网关断定查询条件的规则 ,不符合规则的查询条件直接返回null。

    3.布隆过滤器 :布隆过滤器是一种很是高效的数据结构,把全部数据库的value对应的key 存储到布隆过滤器里,几乎不消耗什么空间,并且查询也是至关的快!可是请注意,它只能判断 key 是否存在(判断必定不存在,可能存在)。

 

Redis 的并发竞争问题如何解决,了解 Redis 事务的 CAS 操做吗


      Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis自己没有锁的概念,Redis对于多个客户端链接并不存在竞争,可是在Jedis客户端对Redis进行并发访问时会发生链接超时、数据转换错误、阻塞、客户端关闭链接等问题,这些问题均是因为客户端链接混乱形成。对此有2种解决方法:

1.客户端角度,为保证每一个客户端间正常有序与Redis进行通讯,对链接进行池化,同时对客户端读写Redis操做采用内部锁synchronized。

2.服务器角度,利用setnx实现锁。

MULTI,EXEC,DISCARD,WATCH 四个命令是 Redis 事务的四个基础命令。其中:

MULTI,告诉 Redis 服务器开启一个事务。注意,只是开启,而不是执行 

EXEC,告诉 Redis 开始执行事务 

DISCARD,告诉 Redis 取消事务 

WATCH,监视某一个键值对,它的做用是在事务执行以前若是监视的键值被修改,事务会被取消。 能够利用watch实现cas乐观锁 
 

 

14.跨域问题的解决方案

     jsonp解决跨域(不推荐,只支持get)

    设置响应头容许跨域:response.setHeader("Access-Control-Allow-Origin", "*");

    使用HttpClient进行转发实现跨域

    SpringBoot设置corsFilter实现跨域:

    搭建nginx api接口网关实现跨域

 

 

15.应用集群时,怎么防止job重复执行

     使用分布式任务调度中心(xxl-job)

 

 

总结:

   由于我19年才毕业,面试问的问题都比较简单,总的来讲以下方面几乎必问:

    数据结构(hashmap  concurrenthashmap)     多线程(线程建立方式, 线程池原理,ThradLocal原理,volatile,CAS,锁)

    数据库(分页,索引,优化)           jvm(内存结构判断对象是否存活垃圾回收算法,gc流程,垃圾收集器(cms,g1))

    框架 (aop ,mvc流程,事务)     redis(数据结构,持久化机制 )