java个人面试总结

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

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

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

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

 

2.HashMap什么时候扩容,每次扩容多少,为什么?

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

扩容大小:每次扩容一倍

为什么扩容一倍:1.容量为2的n次方时,可以减少hash碰撞     2.计算位置时通过位运算,而不是取模可以使效率提高,源码如下:

e.hash & (newCap - 1)

 

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

问题:

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

    2.生产环境中, map 在放入时竞争同一个锁的概率非常小,分段锁反而会造成更新等操作的长时间等待。

    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的底层实现原理以及锁的升级 参考这篇文章(真的不错 ):

                                         https://blog.csdn.net/tongdanping/article/details/79647337

  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(数据结构,持久化机制 )           

 

 

 

 

 

 

 

 

    

    

      

 

    

 

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值