java - 面试总结

  1. java基础,接口和抽象类的区别
    1. 抽象类可以有默认实现方法,接口不行(jdk1.8中接口也可以有默认实现方法以default为访问修饰符)
    2. 多实现,单继承
    3. 接口的访问修饰符只能是public,抽象类还可以有protect
    4. 抽象类可以有构造器
  2. Jdk1.8增加特性
    1. 红黑树
    2. Lamda、stream:允许通过表达式来代替功能接口,Java SE 8添加了2个对集合数据进行批量操作的包: java.util.function 包以及java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了许多额外的功能。 总的来说,lambda表达式和 stream 是自Java语言添加泛型(Generics)和注解(annotation)以来最大的变化。简单的Lambda表达式可由逗号分隔的参数列表、->符号和语句块组成
    3. 方法引用,使得开发者可以直接引用现存的方法、Java类的构造方法或者实例对象。方法引用和Lambda表达式配合使用,使得java类的构造方法看起来紧凑而简洁,没有很多复杂的模板代码。对象::new ;对象::方法
  3. Servlet生命周期,如何运行,与springmvc的区别
    1. web容器(Tomcat)启动并初始化web应用,2.如果客户端请求的servlet不存在则创建servlet实例,3.初始化实例,4.调用service方法,5.输出相应结果,6一段时间没有请求会调用destroy()方法销毁servlet
    2. servlet性能最佳,是处理Http请求的标准,具体开发中需要自己去web.xml中配置servlet节点,比较麻烦;SpringMVC中dispatchServlet(继承自HttpServlet)会拦截所有的请求,进一步查找是否有合适的处理器等等,同时还会有视图渲染
  4. Springmvc请求流程
  5. 注解是如何实现功能的
    1. 注解的本质是接口,在运行时,通过动态代理生成该接口的子类,反射到他的方法
  6. 事物,spring如何处理处理,事物回滚发生的条件,脏读,幻读,不可重复读,声明式事物:这意味着你可以将业务代码和事务管理分离,你只需用注解和 XML 配置来管理事务。
    1. spring提供了声明式事务和编程式事务,实际开发中声明式事物较多,
    2. a)事物回滚发生的条件:两条关联数据插入两张表中,如果一条数据出现异常,可以进行事物回滚,b)数据存了一半数据库宕机或者网络情况回滚,c)数据库预执行的数据库资源没有commit,connection连接没有关闭,导致资源一直没有释放,易引起数据库提交超时,或者机制自动回收资源,会把数据库缓存的事物回滚
    3. 脏读:A事务读取B事务尚未提交的更改数据,并在这个数据的基础上进行操作,这时候如果事务B回滚,那么A事务读到的数据是不被承认的。例如常见的取款事务和转账事务:
    4. 不可重复读:是指A事务读取了B事务已经提交的更改数据。假如A在取款事务的过程中,B往该账户转账100,A两次读取的余额发生不一致
    5. 幻读:A事务读取B事务提交的新增数据,会引发幻读问题。幻读一般发生在计算统计数据的事务中,例如银行系统在同一个事务中两次统计存款账户的总金额,在两次统计中,刚好新增了一个存款账户,存入了100,这时候两次统计的总金额不一致
    6. 悲观锁:每次拿数据都会上锁,乐观锁:每次拿数据不需要加锁,但是更新数据的时候需要加版本号去判断乐观锁适用于多读的应用类型,这样可以提高吞吐量;悲观锁多用于写入更新频繁,强一致性的场景,效率较低
    7. 如果并发量不大且不允许脏读,可以使用悲观锁解决并发问题;但如果系统的并发非常大的话,悲观锁定会带来非常大的性能问题,所以我们就要选择乐观锁定的方法.
  7. SpringIOC容器,aop(如何对一个方法进行aop)
      1. ioc设计思路:BeanFactory和ApplicationContext
      2. 而BeanFactory又是Ioc容器的最基本的接口,在ApplicationContext的设计中,一方面,可以看到他继承了HiearerchialBeanFactory等BeanFactory的接口,具备了BeanFactory Ioc容器的基本功能,另外一方面,通过继承MessageSource、ResourceLoader、ApplicationEventPublisher这些接口,BeanFactory为ApplicationContext赋予了更高级的Ioc容器特性。对于ApplicationContext而言,为了在Web环境中使用它,还设计了WebApplicationContext接口,而这个接口通过继承ThemeSource接口来扩充功能。
      3. AOP  动态代理,jdk、cglib动态代理;aspectJ动态代理框架
  8. Sql优化(mysql引擎)、执行计划(未完待续)
    1. 增加索引  单独用CREATE INDEX或ALTER TABLE来给表增加索引。删除索引可以利用ALTER TABLE或DROP INDEX
    2. 不使用通配符%(使用了通配符就不使用索引)
    3. 尽量不用子查询,使用join
    4. 使用union代替临时表
    5. 不使用in、or、not in,使用exists,not exists   in和or所在列有索引或者主键的话,or和in没啥差别,执行计划和执行时间都几乎一样。如果没有索引,则效率会低很多,in的执行过程相当于循环执行查找很多遍,且缓存结果,最后结果相加,而exists则不会,exists中的结果只是用来做判断的,true or false
    6. sql执行计划,即在sql前加上  EXPLAN ,得出来的结果会判断出几个子查询,使用索引情况等
    7. 索引的建立条件:A)数据量足够大,B)针对字段建立,一般在where条件,order by ,group by后面可以加索引
    8. mysql会统计索引的重复度,优先选用低重复的字段,如果选择高重复字段则空间成本较大  E:select from students where name='张三’and age=18;  此时如果要建立索引,一般选择name字段,name字段重复率低
    9. 联合索引比较好呢? 举一个例子,大学修课,需要创建一个关系对应表,有2个字段,student_id 和 teacher_id,想要查询某个老师和某个学生是否存在师生关系。
      一个学生会选50老师,一个老师会带200个学生
      如果只为student_id建立索引的情况下,经过索引会选出50条记录,然后在内存中where一下,去除其余的老师。
      相反如果只为teacher_id建立索引,经过索引会选出200条记录,然后在内存中where一下,去除其余的学生。
      两种情况都不是最优的,因为使用索引后范围依然很大,这个时候使用联合索引最合适,通过索引直接找到对应记录,差不多提高了一倍效;https://www.cnblogs.com/orchidbaby/p/7704407.html
    10. 全文索引:fulltext,语法与基本索引一样;在MySQL中,创建全文索引相对比较简单。例如,我们有一个文章表(article),其中有主键ID(id)、文章标题(title)、文章内容(content)三个字段。现在我们希望能够在titlecontent两个列上创建全文索引,article表及全文索引的创建SQL语句如下:CREATE TABLE (xxxx, FULLTEXT(title,context))  ---- 在title和content上建立全文检索;sql创建:Alter table xx add fulltext index fulltext_tablename(title,context);  创建完成之后,如果需要使用模糊查询,可以使用,select * from tablename where MATCH(tltie,context) AGAINST('关于xxx');强烈注意:MySQL自带的全文索引只能用于数据库引擎为MyISAM的数据表,如果是其他数据引擎,则全文索引不会生效。此外,MySQL自带的全文索引只能对英文进行全文检索,目前无法对中文进行全文检索。如果需要对包含中文在内的文本数据进行全文检索,我们需要采用Sphinx(斯芬克斯)/Coreseek技术来处理中文
    11. 索引失效的情况:1、使用了is nul;2、重复数据较多的列;3、通配符%;4、条件中有or关键字(必须or的条件全部都有索引才会生效);5、
    12. mysql中如果表的数据发生改变,那么索引也会自动改变,所以索引不能乱加,否则带来的mysql内存开销,更改索引的过程也会更长
  9. 线程池的各个概念,应用场景,十个线程执行一段代码,执行完成之后才能进入下一个方法,如何解决(countdownlanch)
    1. fixedThreadPool: 固定数量的线程 处理一个 共享的无边界队列 。不会自动销毁,需要手动执行销毁方法,所以 FixedThreadPool 多数针对一些很稳定很固定的正规并发线程,多用于服务器 
    2. cachedThreadPool:  如果线程池中有休眠的线程,就直接启动,适用场景:大量短生命周期的异步任务
    3. singleThreadPool: 单例的线程池,永远只有一个线程,适用于串行任务
    4. scheduledThreadPool创建一个固定大小的线程池,线程池内线程存活时间无限制,线程池可以支持定时及周期性任务执行,如果所有线程均处于繁忙状态,对于新任务会进入DelayedWorkQueue,适用于周期性任务,定时任务
    5. workstealingThreadPool,工作窃取,即开固定个数线程的线程池,每个线程执行完任务后,继续执行其他任务
    6. forkjoin,用于大型计算
  10. Spring作用域,
    1. Singleton(单例)(默认),propotype(多例),web应用下request(每次请求都会产生一个,且只在请求内有效),session(示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效),global(相当于定义了一个全局session)
  11. RESTful的基本概念,webService接口与restful接口的使用场景
    1. restful就是http架构风格,定义了如何编写,定义返回值,定义状态码的,显著特点:URL的不一样,根据请求方式的不同,对应的参数;每一个URL代表一种资源
    2. a)webService接口适用SOAP协议,不同平台,不同语言之间都可以用,b)webservice接口安全性好,cwebService接口可能会由于业务过多,过于臃肿,且在大并发下,性能有所下降;
    3. restful接口,轻量级接口,完全通过HTTP协议实现,还可以利用缓存来提高速度,性能,效率;容易使用
  12. 消息队列,ack概念,消息队列的应用场景,设计思路
    1. 消息队列已经逐渐成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能,成为异步RPC的主要手段之一。
    2. 业务场景:业务解耦、最终一致性、广播、错峰流控
    3. 设计思路:一般来讲,设计消息队列的整体思路是先build一个整体的数据流,例如producer发送给broker,broker发送给consumer,consumer回复消费确认,broker删除/备份消息等。
      利用RPC将数据流串起来。然后考虑RPC的高可用性,尽量做到无状态,方便水平扩展。
      之后考虑如何承载消息堆积,然后在合适的时机投递消息,而处理堆积的最佳方式,就是存储,存储的选型需要综合考虑性能/可靠性和开发维护成本等诸多因素
  13. 缓存穿透、击穿、雪崩如何排查解决;
    1. 缓存穿透:即缓存不起作用,请求直接访问数据库,导致数据库访问量过大
      1. 采用布隆过滤器,使用一个足够大的bitmap,用于存储可能访问的key,不存在的key直接被过滤;
      2. 访问key未在DB查询到值,也将空值写进缓存,但可以设置较短过期时间。
    2. 缓存雪崩:缓存出现大面积同时失效,新的缓存未能及时更新上
      1. 可以给缓存设置过期时间时加上一个随机值时间,使得每个key的过期时间分布开来,不会集中在同一时刻失效。
    3. 缓存击穿:某个key,在缓存过期的一刻,同时又大量请求直接请求到数据库,造成数据库压力大
      1. 在访问key之前,采用SETNX(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。
  14. Redis的各个数据类型分别对应哪些使用场景:参考:https://www.cnblogs.com/lizhenghn/p/5322887.html(整理的很好的文章)
    1. String(字符串):String是最常用的一种数据类型,普通的key/value存储都可以归为此类
    2. List(列表)Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构
    3. Hash(字典)Redis Hash对应Value内部实际就是一个HashMap,多个用户及对应的用户信息,可以用来存储以用户ID为key,将用户信息序列化为比如json格式做为value进行保存(Session共享
    4. Set(集合)理解为一堆值不重复的列表,Redis也提供了针对集合的求交集、并集、差集等操作,功能与List类似,特殊之处在于Set是可以自动排重的;set的内部是一个value永远为null的HashMap;就是通过计算hash值来快速排重,场景:微博中每个关注的人存在一个集合中,这样就可以判断出共同好友
    5. Sorted Set(有序集合)内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。场景:比如用户的积分排行榜需求就可以通过有序集合实现
  15. Dubbo架构中的各个框架(了解)‘
    1. zookeeper注册中心,服务治理,集群个数最少3台机器,集群后会投票选出leader,两个follower
  16. 集合,hashmap源码
    1. HashMap 实现了Map接口,<K,V>key ,value 都可以为空,除了不是线程安全,和允许为null之外,几乎与HashTabel相同,
    2. 一个HashMap主要有两个参数,capacity(桶的容量)(默认16),load factor(负载因子)(默认0.75);
      1. put原理  :https://blog.csdn.net/shumoyin/article/details/80243419     ;https://www.cnblogs.com/kangkaii/p/8473793.html
        1. hash(key) 取key的hashcode进行高位运算,返回hash值        
        2. 如果hash数组为空,直接resize()
        3. 对hash进行取模计算,得到key-value 在数组中的存储位置
        4. 如果table[i] == null 直接插入Node<key,value.>               
        5. 如果table[i] != null 判断是否为红黑树 p instanceof TreeNode   
        6. 如果是红黑树,判断TreeNode是否存在,存在返回TreeNode并更新,不存在插入红黑树,超出容量,进行扩容
        7. 如果是链表,判断Node是否存在,如果存在返回oldNode并更新,不存在直接插入链表尾部,判断链表长度,如果大于8,转为红黑树,超出容量,扩容;                                                  
  17. Spring boot,spring cloud(需要精通概念)
    1. spring boot优势,spring cloud的各大组件
  18. Jbpm与activiti
  19. Luncence与solr、ElasticSearch 关于Luncence:https://blog.csdn.net/cying90/article/details/84342587()非常全的解读
    1. 关键:倒排序索引
    2. 创建索引的过程:1、将数据对象转化为Document,其中的属性转化为Field;2、调用工具IndexWriter的addDocument(doc) ,将document添加到索引库中;3、luncence做的操作:将文档存到索引库中,并自动指定一个索引编号,用来做唯一标识符;内部编号类似数据的地址,在索引库内部的数据进行调整过后,这个编号可能会改变,同时词汇表(类似目录引用)中引用的编号也会改变4、更新词汇表,把文本中的词找出来放到词汇表中,建立与文档的对应关系,此处运用到了分词器(analyzer)工具;doc.add(new Field("title", article.getTitle(), Store.YES, Index.ANALYZED))----把对象的属性转为代码;
    3. 全文 检索的过程:现在词汇表中进行查找,得到符合条件的文档编号列表,在根据文档编号真正的去解析数据(doucment);具体步骤:a)查询字符串Query对象,查询字符串可以使用Queryparser或者mulitiFiledQueryParaser.,查询字符串也要经过Analyzer,要求你搜索时的Analyzer与建立索引的Analyzer一致;C)调用IndexSearcher.search(),进行查询,得到结果返回TopDocs,包含多个信息的对象,其中有totalHits,代表记录数,ScoreDoc的数组代表与搜索结果相对应的信息;此后再调用IndexSearcher.doc(ScoreDoc.doc)取出指定编号的Document数据;调用完毕后需要关闭IndexSearcher.close()
    4. 常用API:IndexWriter(创建索引类),Query,Sort,IndexSearcher(检索类),TopDocs(文档结果集),SimpleHTMLFormatter,Highlighter,ScoreDoc[] (数据结果集),IKAnalyzer(分词器)
    5. 在ElasticSearch中,可以直接用spring自带的ElasticSearchTemplete.createIndex(Pojo.class).puMapping(pojo.class)可以用Esresposity.findAll();查;.save()增,saveALl()增;findALl()查找所有;findBetween(条件查询);也可以用原生的查询来构建:NativeSearchQueryBuild 
              //原生查询过滤条件
              NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
              //结果过滤
              queryBuilder.withSourceFilter(new FetchSourceFilter
                      (new String[]{"id","title","price"},null));
              //增加查询条件
              queryBuilder.withQuery(QueryBuilders.matchQuery("title","小米手机"));
              //增加排序
              queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
              //分页
              queryBuilder.withPageable(PageRequest.of(0,5));
              Page<pojo> result = esresposity.search(queryBuilder.build());
      //可以自定义查询
      public interface Esresposity extends ElasticsearchRepository<pojo,Long> {
          //自定义查询,根据findBy,等关键字动态帮你处理
          //支持排序,pageable
          List<pojo> findByPriceBetween(Double str,Double end);

       

  20. Spring的其他框架
  21. Math,Random函数
  22. RPC底层协议的构成(未完待续)
    1. 一个典型RPC的使用场景中,包含了服务发现、负载、容错、网络传输、序列化等组件
  23. Session、Cookie是什么,他们如何记录到Redis中
    1. session:服务器可以为每个用户浏览器创建一个会话对象(session对象),Session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象;
    2. Session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。
    3. Cookie是把用户的数据写给用户的浏览器。
    4. @EnableRedisHttpSession注解,在启动类上注明,这样项目启动后,如果有用户访问,那session就会被记录到redis中
  24. 为什么Synchronized锁是可重入的锁,Lock锁如何实现公平锁,Volitie如何实现可见性
    1. 不同对象实例的synchronized方法是不相干预
    2. 修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁
    3. 修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁
    4. 修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁
    5. volatile:每个线程读取主内存的时候会现在线程缓存中存一份,在合适时机会写回去,写回去后会通知其他线程,如果还未写回去,那另一个线程访问的内容可能不是最新的内容了

      volatile:挥发性关键字:作用:当一个线程改变挥发性修饰的对象后,则b线程如果在访问该对象,则也会重新读取对象使用挥发性将会强制所有线程都去堆内存中读取被挥发性修饰的对象

    6.  public static ReentrantLock lock = new ReentrantLock(true);//定义一个公平锁;lock.lock(); //手动加锁;finally{lock.unlock();} //手动释放锁

  25. Eureka的原理模型,如何实现心跳机制的
    1. Eureka包含两个主要部分 Eureka Server 和 Eureka Client,在服务启动后Eureka Server提供服务发现的能力,各个微服务启动时,Eureka Client会向Eureka Server通过http请求注册自己的信息,注册的信息会维护在Eureka Server中的一个HashMap中,
    2. 微服务启动后,会周期性地向Eureka Server发送心跳(存储在Eureka Server中的Hashmap)(默认周期为30秒)以续约自己的信息。如果Eureka Server在一定时间内没有接收到某个微服务节点的心跳,Eureka Server将会注销该微服务节点(默认90秒);
    3. Eureka Client会缓存Eureka Server中的信息。即使所有的Eureka Server节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者。
  26. 集合框架,其他集合如何相互转化,集合区别
    1. Collection 接口是所有list、set集合的父接口
    2. Collections.sort方法,compareto方法;https://blog.csdn.net/qq_36239350/article/details/81782755
    3. List.toArray;arr.asList()
    4. treeSet转arraylist list.addAll(treeset)
    5. https://blog.csdn.net/qq_41820981/article/details/88241650
  27. Eureka如何治理服务,与Zookeeper比较
    1. CAP:分布式系统中有三个方面需要权衡:  一致性(consistency) 可用性(availability) 分区容忍性(partition tolerence),Eureka是AP原则,牺牲掉了一部分数据一致性,Zookeeper是CP原则(选取leader的过程,整个zookeeper集群不可用)
  28. 数据库连接池连接原理,执行过程
    1. 资源重用,避免频繁创建、销毁连接,减少系统消耗的同时,增加了系统的稳定性
    2. 更快的相应速度,连接池在初始化阶段就已经创建好了若干的数据库连接放置于池中备用,此时连接的初始化工作已经完成,如果有请求,则直接调用即可
    3. 统一的连接管理,如最大连接数,强制回收机制,避免连接过程出现资源泄露
    4. 执行过程:请求 --判断是否有可用的连接,有就直接用,用完销毁,归还到连接池,没有就创建一个(没有超过最大连接数),用完销毁归还到连接池
  29. webSocket编程,io编程,NIO概念
    1. https://www.cnblogs.com/biehongli/p/6074713.html   输入输出流总结
  30. threadlocal使用场景
    1. 线程本地变量,即修饰某个变量,每个线程访问的这个变量的时候,会创建自己的变量副本
    2. ThreadLocal使用场景为 用来解决 数据库连接、Session管理等。
  31. 设计模式,工厂模式,代理模式,观察者模式
  32. 负载均衡的算法:轮询,加权轮询,
  33. mysql分表操作;当数据量越来越大的时候,读取数据的速度会越来越慢,此时如果还有联合查询,则会直接卡死
    1. 做mysql集群,利用mysql cluster,mysql proxy,mysql replication,linux mysql  proxy进行读写分离;mysql replication 互为主从关系安装配置,以及数据同步,缺点是:硬件消耗大,单表数据容易变大
    2. 预估数据量,对主业务表(读写频繁)预先进行设置,创建多个从表,例如message表可以分为message_01....100可以通过用户的id取hash值,或者取余的方式决定哪些用户的数据放在哪些表中,优点:避免 了一张表出现几百万条数据,缺点是当规则确定之后,打破规则很难
    3. 垂直切分,指针对一些模块间较为独立的系统,以模块为原则切分,以缓解大数据的压力,涉及到快节点的join问题
    4. 水平分表分库:a)按号段分:user_id为区分,1-1000,1001-2000~~优点:可以部分迁移,缺点数据分割不均;b)hash取模:对特定的值如user_id进行hash取模,例如某个应用中需要将数据库分为四个数据库的时候,可以用4这个数字对user_id的hash值进行取模运算,也就是user_id.hash%4;此时可以把数据均匀的分布到4个DB上,优点:数据分布均匀,缺点:数据迁移的时候麻烦,C)从认证库中保持数据库配置,建立一个DB,这个DB单独保存user_id到DB的映射关系,每次数据库访问都需要先查询一次这个数据库,得到具体的DB信息,然后进行接下来的操作,优点:灵活,缺点:效率低,性能差,D)
    5. 利用Merge存储引擎实现分表(最佳选择):
    6. 数据库切分之后的问题:1、保证ID全局的统一;,快节点的join问题,跨节点合并排序问题,以及分布式事物处理,(深度好文推荐:)https://www.cnblogs.com/zlazm/p/9294291.html;通过id生成映射表
  34. mysql5.7版本之后重要升级是什么:
    1. 性能大大提高
    2. new json数据类型和函数支持,json也可以在Text或者varchar里用内置的json,更容易访问,json列类型及以json_开头的相关处理函数,如json_type(),json_object(),json_merge()等
    3. 支持虚拟咧,以及虚拟列上的索引,不存在磁盘上
    4. InnoDb引擎增强
  35. 如何对系统进行重构
    1. sql优化,代码优化,性能优化
  36. mysql读写分离
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值