Java面试经验总结

Java面试知识点

这里总结一下Java面试的一些经验和需要主要准备的一些内容 ,内容除了Java知识以外,基本也需要准备一些前端、数据库、主流框架等一些技术及底层原理的知识,同时也需要一些项目经验的详细介绍和说明一些解决问题的能力。

基础常识

  1. 软件生命周期 :可行性研究、需求分析、设计(概要设计和详细设计)、编码、测试(黑盒测试和白盒测试)、维护;

  2. **String区别(Java和C++)😗*Java中其是常量具有不可变性,C++中是变量是可变的;

  3. java三大架构JavaEE(web) javase(桌面应用程序) javame(手机移动应用程序);

  4. java分为五大区(寄存器(程序计数器),本地方法区(静态方法,方法区(动态方法),栈(存储局部变量),堆(存储数组和对象实体);

  5. **Java常用的设计模式:**单例模式(保证一个类只有一个实例),工厂模式(简单工厂方法模式(由一个具体的类去创建其他类的实例),工厂方法模式(由抽象父类定义公共接口,子类负责生成具体的对象),抽象工厂模式(创建一个系列相关相互依赖对象的接口,无需实现具体的类));

  6. 三次握手
    刚开始客户端处于 closed 的状态,服务端处于 listen 状态。然后
    1、第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN(c)。此时客户端处于 SYN_Send 状态。
    2、第二次握手:服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,并且也是指定了自己的初始化序列号 ISN(s),同时会把客户端的 ISN + 1 作为 ACK 的值,表示自己已经收到了客户端的 SYN,此时服务器处于 SYN_REVD 的状态。
    3、第三次握手:客户端收到 SYN 报文之后,会发送一个 ACK 报文,当然,也是一样把服务器的 ISN + 1 作为 ACK 的值,表示已经收到了服务端的 SYN 报文,此时客户端处于 establised 状态。
    4、服务器收到 ACK 报文之后,也处于 establised 状态,此时,双方以建立起了链接。
    三次握手

  7. 四次挥手
    1、第一次挥手:客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于FIN_WAIT1状态。
    2、第二次握手:服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 + 1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT状态。
    3、第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 的状态。
    4、第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 + 1 作为自己 ACK 报文的序列号值,此时客户端处于 TIME_WAIT 状态。需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态
    5、服务端收到 ACK 报文之后,就处于关闭连接了,处于 CLOSED 状态。
    四次挥手
    至于 TIME_WAIT 持续的时间至少是一个报文的来回时间。一般会设置一个计时,如果过了这个计时没有再次收到 FIN 报文,则代表对方成功就是 ACK 报文,此时处于 CLOSED 状态。

  8. elasticsearch企业级搜索引擎分布式全文搜索

  9. 正则表达式
    /\d**[\d][\w]{6}$/,下面的字符串中哪个能正确匹配?(C)
    解释:\d
    表示以数字开头,排除AB选项,* 匹配一个星号,[^\d]匹配任意非数字字符,[\w]{6}匹配包括下划线在内的数字及字母字符6个,D选项有连接符-,排除掉。单个是匹配前面的子表达式零次或多次
    A、abcABCD_89 B、abcabcABCDEF C、123abcABCD_89 D、123ABCabcd-89

  10. 为什么需要缓存?常用的缓存有哪些?以及淘汰策略有哪些?
    因为我们从磁盘中读取文件的速度相较于读取内存中的数据的速度是比较慢的,因此我们需要把常用的数据放入内存中即缓存,以加快数据的读取速度。
    常用的缓存有memcache、redis、webcache等,
    淘汰策略有FIFO先进先出、LRU最近最少使用、LFU最不经常使用。

  11. B/S架构、C/S架构是什么,区别
    B/S是浏览器和服务器架构模式,C/S是客户端和服务器的架构模式

  12. 重定向和反转是什么(区别)
    重定向(redirect)特点:
    1.地址栏路径可以发生改变
    2.重定向可以访问其他站点(服务器)的资源
    3.重定向是两次请求,不能使用request对象共享数据
    转发(forward)的特点:
    1.转发地址栏路径不变
    2.转发只能访问当前服务器下的资源
    3.转发是一次请求,可以使用request对象共享数据

前端基础知识

1、前端性能的优化有哪些?
1、减少http请求数
2、图片优化:尽可能使用PNG图片
3、使用CDN:CDN即内容分化网络,可以使用户就近取得所需内容,解决网络拥挤的状况,提高用户访问网络的响应速度。
4、开启GZIP:GZIP即数据压缩,用于压缩使用Internet传输的所有文本资源。在web服务配置文件中httpd.conf中添加。
5、样式表和JS文件的优化:一般把css样式放在文件的头部,标签中,js脚本文件一般放在页面的尾部。
6、使用无cookie域名:请求用不到cookie时(请求一些静态文件)不使用cookie

2、Get Post区别
1、Get和post最大的区别是get产生一个TCP数据包(浏览器会把http header和data一并发送出去。服务器响应200返回数据);post产生两个TCP数据(浏览器先发送header,服务器响应100,之后浏览器再发送data,服务器响应200返回数据)。Firefox就只发送一次。
2、Get是从服务器上获取数据(查询数据),post是向服务器传送数据(数据的添加、修改、删除)。
3、Get是把请求的数据放在URL上面,即http的协议头上,post把数据放在http的包体内(request body)。Post比get安全。
4、Get请求参数通过URL传递,所以传送的参数是有长度限制的,post请求方法在request body中,没有参数长度的限制。(实际上有限制,但是比get长很多)
5、Get在浏览器回退时是无害的,而post会再次请求提交。
6、Get请求会被浏览器主动cache,而post不会除非手动设置
7、Get请求只能进行URL编码(ASCII字符),而post支持多种编码方式。
8、Post那么好用为什么用get?因为get效率高

3、css中有哪些选择器,一一列举并说明
1、id选择器(#box):选择id为box的元素。
2、类选择器(.one):选择class为one的元素。
3、标签选择器(div):选择标签为div的所有元素。
4、后代选择器(#box div):选择id为box的内部所有的div元素。
5、子选择器(.one>one_1):选择父元素为.one的所有.one_1的元素。
6、相邻兄弟选择器(.one+.two):选择紧接在.one之后的所有.two元素。
7、伪类选择器:
(1):first-child:父元素的首个子元素;
(2):nth-child(n):根据元素在一组同级中的位置匹配元素;
(3):last-child:父元素的最后一个子元素。

Java基础知识

1、并行与并发

1、并发:并发是指两个或多个事件在同一时间间隔发生。
2、并行:并行是指两个或者多个事件在同一时刻发生。
1、并发:并发在一台处理器上“同时”处理多个任务。
2、并行:并行在多台处理器上同时处理多个任务。

2、线程与进程

进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1 — n个线程。多进程是指操作系统能同时运行多个任务(程序)
线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。多线程是指在同一程序中有多个顺序流在执行。

3、HashMap和HashTable区别

1、线程安全性上
hashMap线程不安全,在多线程并发会造成死锁问题,但是效率比hashtable高,大部分都是单线程操作。
HashTable是线程安全的,每一个方法都加了锁,适用于多线程并发环境。
2、继承的父类不同
HashMap是继承AbstractMap类
HashTable 是继承Dictionary类,
3、初始容量大小和每次扩容大小不同
HashMap默认初始大小为16 每次扩容为2倍
HashTable默认的初始大小为11每次扩容为2n+1
4、key和value是否允许为null值
HashMap可以允许key和value为空存储在数组索引为0处
HashTable中,key和value都不能为null
5、遍历方式不同
Hashtable比Hashmap多一个elements方法

4、new对象创建过程原理(在JVM),从执行的角度(其他角度待续)

1、当JVM遇到字节码new指令时,首先将检查该指令的参数能否在常量池中定位到一个类的符号引用,并检查引用代表的类是否已被加载、解析和初始化,如果没有就先执行类加载。
2、在类加载检查通过后虚拟机将为新生对象分配内存。
3、内存分配完成后虚拟机将成员变量设为零值,保证对象的实例字段可以不赋初值就使用。
4、设置对象头,包含哈希码、GC信息、锁信息、对象所属类的类元信息等。
5、执行init方法,初始化成员变量,执行实例化代码块,调用类的构造方法,并把堆内对象的首地址赋值给引用对象。

4、Volatile和Synchronized

volatile是什么
Volatile修饰的变量可以完成多线程之间变量可见,因为不是原子性操作,所以线程不安全。无锁
Synchronized修饰的变量是原子性操作,有同步互斥锁

5、线程创建的几种方法

1、定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run方法称为执行体。创建Thread子类的实例,即创建了线程对象。调用线程对象的start()方法来启动线程。
2、定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法同样是线程的执行体。创建Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。调用线程对象的start()方法来启动该线程。
3、创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且返回值。

6、垃圾回收机制原理

首先需要判断对象是否死亡,这里主要有引用计数法和可达性分析算法两种来判断对象是否死亡:引用计数法给对象添加一个引用计数器,每当有引用它时计数器就加一,当引用失效时计数器减一,当计数器为0时则可判别对象死亡。(不能解决对象之间相互循环引用的问题);可达性分析算法通过一些称为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象没有引用链时则证明这个对象不可用。
GC Roots有哪些:栈中的本地变量、静态变量、同步锁synchronized关键字持有的对象。
确定了对象是否死亡之后就要根据垃圾收集算法来进行回收。主要有标记-清除算法(标记是通过前面识别对象是否死亡过程,清除是一次性清除)、标记-复制算法(将内存按容量分为大小相等的两块,每次只使用其中一块,当一块内存用完了,就将还存活的对象复制到另一块中,然后把之前使用满的那一块直接一次清理掉)、标记-整理算法(标记同理,不直接清理无用对象,而是向后移动,清除边界外的内存)、分代收集算法(将堆内存分为新生代、老年代、永久代将不同周期的对象分代,不同的代采取不同的回收算法进行垃圾回收,以便提高回收效率。其中新手代是那些生命周期短的对象-采用标记复制算法、老年代是存放那些生命周期较长的对象-标记清除或者标记整理算法,永久代是存放一些静态文件-JDK1.8开始废弃,取代的是元空间(直接存在内存中可自定义大小),存放类的元数据)。

7、.class在jvm里面执行原理过程

JVM会将编译生成的.class文件按照需求和一定的规则加载到内存中,并组织成为一个完整的Java应用程序。这个加载过程是由类加载器完成,具体来说,就是由ClassLoader和它的子类来实现的。类加载器本身也是一个类,其实质是把类文件从硬盘中读取到内存中。类的加载方式分为隐式加载和显式加载。隐式加载是指程序使用new等方式创建对象时,会隐式地调用类的加载器把对应的类加载到JVM中。显式加载是指通过直接调用classforName()方法来把所需的类加载到JVM中。类加载的主要步骤:装载,通过路径找到相应的class文件然后导入。链接,检查正确性,准备空间,解析引用。初始化,对静态变量和静态代码块执行初始化工作。

8、IO流

IO流:字符流(reader\writer)、字节流(InputStream\OutputStream)

9、Java创建对象

4种创建对象方法:
1、使用new关键字调用对象的构造器
2、使用java反射的newInstance()方法
3、使用Object类的clone()方法
4、使用对象流ObjectInputStream的readObject()方法读取序列化对象

10、线程安全性理解

当多个线程访问一个对象时,如果不用进行额外的同步控制或其他的协调操作,调用这个对象的行为都可以获得正确的结果,我们就说这个对象是线程安全的。
如何做到线程安全呢?常见的方式有synchronized关键字给代码块或方法加锁。什么时候需要线程安全呢?首先在多个线程访问同一个资源;其次,资源是有状态的,比如我们上诉讲的字符串拼接,这个时候数据是会有变化的。

11、Java锁

Java锁作为并发共享数据,保证一致性的工具,在Java平台有多种实现:synchronized和ReentrantLock等。Java锁的种类有公平锁、非公平锁、可重入锁、独享锁、共享锁、互斥锁、读写锁、乐观锁、悲观锁、分段锁、偏向锁、轻量级锁、重量级锁、自旋锁等。

12、Java集合

List set map之间的区别和有些子类以及子类的说明
List是元素有序、允许元素重复
List:ArrayList\LinkedList、Vector\Stack
Set:无序、不能重复
HashSet\LinkedHashSet\TreeSet
Map:键值对、键唯一、值不唯一
HashMap\HashTable\LinkedHashMap\TreeMap

HashMap是怎么实现的?
1、JDK1.7的HashMap是用数组+链表实现的、头插法(长度16)。
2、JDK1.8的HashMap是用数组+链表+红黑树(在二叉平衡树AVL基础上保证插入删除时少量的旋转操作,整体性能优于AVL,比二叉搜索树多了颜色属性和parent属性)实现的、尾插法(长度超过8就换红黑树)。

13、Jvm内存模型以及如何调优

JVM内存模型分为程序计数器、本地方法区、方法区、堆(主要存放一些数组和对象实例)、栈(存放一些局部变量)
调优的最终目的是为了令应用程序使用最小的硬件来承载更大的吞吐。
JVM优化的步骤流程一般是:
1、分析GC日志及dump文件,判断是否需要优化,确定瓶颈问题点。使用jps -v jmap -dump查看。优化的问题一般有垃圾回收GC次数频繁、GC停顿时间过长、内存溢出异常、占用大量内存空间、吞吐量与响应性能不高或下降。
2、确定JVM调优量化目标。
3、确定JVM调优参数。
4、调优一台服务器,对比观察调优前后的差异。
5、不断的分析和调整,直到找到合适的JVM参数配置。
6、知道合适的参数,将这些参数应用到所有服务器,并进行后续跟踪。

14、重写和重载是什么

方法的重写和重载是 Java 多态性的不同表现。重写是父类与子类之间多态性的一种表现,重载是一个类中多态性的一种表现
如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写。
如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载。

15、反射是什么原理是

答:反射机制是在运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意个对象,都能够调用它的任意一个方法。在java中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
通过new创建对象的效率比较高。通过反射时,先找查找类资源,使用类加载器创建,过程比较繁琐,所以效率较低。Java反射可以创建对象。
获取Class对象,有4种方法:(1)Class.forName(“类的路径”);(2)类名.class;(3)对象名.getClass();(4)基本类型的包装类,可以调用包装类的Type属性来获得该包装类的Class对象。

16、多态的三个条件

1、需要有继承关系
2、需要有方法的重写
3、需要有父类的引用指向子类对象。 父类名 a=new 子类名()a.func就是出现多态。

17、接口和抽象类的区别

抽象类是一种对事物的抽象,而接口是一种对行为的抽象;
抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。
抽象类是一种模板式设计,而接口是一种行为规范,是一种辐射式设计。

18、final修饰类、属性方法能不能被继承

1.final修饰类:这个类不能被继承。如:String类、StringBuffer类、System类。
2.final修饰方法:不能被重写。如:Object类的getClass()方法。
3.final修饰属性:此属性就是一个常量,一旦初始化就不可再被赋值。习惯上,常用大写字符表示。

19、什么是构造器

构造器的本质作用就是为对象初始化,即为实例变量初始化,赋初值

20、wait、sleep(后续待补)

Join()通过wait()方法实现的:让主线程等待,一直等到其他线程不再活动为止。

数据库基础知识

1、第一范式第二范式第三范式区别
不包含非原子项属性的关系就是第一范式的关系;对于第一范式的关系,如果此关系中的每个非主属性都完全函数依赖于主键,则此关系属于第二范式;对于第二范式的关系,如果所有的非主属性都不传递依赖于主键,则此关系就是第三范式的。
2、聚合函数:count(),sum(),avg(),min(),max()
3、Mysql数据类型(数值型和字符型)
数值型:
TinyINT:非常小的整数
SMALLINT:较小整数
MEDIMINT中等大小整数
INT :标准整数
BIgINT较大整数
FLoat单精度浮点数
DOBULE双精度浮点数
DECIMAL一个串的浮点数
字符型:
char varchar TINYBLOB、MEDIUMBLOB、LONGBLOB、ENUM、SET
4、Sql查询优化有哪些
索引有哪些:主键索引、唯一索引、普通索引、全文索引、覆盖索引、组合索引
1、创建索引是时,尽量避免全表扫描;
2、尽量使用参数化SQL
3、尽量将多条SQL语句压缩到一句SQL中
4、用where字句替换HAVING字句
5、连接多个表时,使用表的别名
6、尽量避免使用游标等等。

5、Group by、having、Order by的区别和用法
Group by是分组查询一般和聚合函数配合使用
Order by是排序,默认是升序 asc、降序为desc
Having子句是筛选满足条件的组,一般与group by使用
三个执行顺序是where\group by\ having \order by
6、存储过程和视图的区别
存储过程是事先存储好的SQL语句,放在数据库服务器端,需要使用时直接调用存储过程就可以执行相应的SQL语句,可以带参数和返回结果。
视图是一张虚拟表,不存放数据,数据在原来的数据表中,可以进行增删改查。
区别:
1、范围不同,视图一次只能返回一个二维表,且不能接受参数。而视图可以。
2、目的不同,存储过程一般涉及到复杂的数据处理,一般是作为复杂处理的方法使用。而视图一般是为了展示多表查询数据,用于查找多一点。

7、什么是事务,有哪些特性?
事务是把一系列SQL操作打包成一个完整的单元,要么都成功要么都失败。保证数据的一致性。
特性:原子性(事务是一个完整操作,要么执行要么不执行)、一致性(事务完成时数据必须保持一致状态)、隔离性(事务是独立的,不能影响其他事务)、持久性(事务完成后数据库的修改被永久保存,由事务日志保障)

8、Oracle存储过程和函数区别、游标
游标类似指针,游标可以执行多个不相关的操作。存储过程和函数的区别如下所示:
① 函数可以理解为是存储过程的一种;
② 函数可以没有参数,但是一定需要一个返回值,存储过程可以没有参数,不需要返回值;
③ 函数和存储过程都可以通过OUT参数返回值,如果需要返回多个参数那么建议使用存储过程;
④ 在SQL数据操纵语句中只能调用函数而不能调用存储过程。

  1. 游标的定义
    游标(Cursor)是一个存储在DBMS服务器上的数据库查询,它不是一条SELECT语句,而是被该语句检索出来的结果集。在存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据。
  2. 游标的特性
    ① 能够标记游标为只读,使数据能读取,但不能更新和删除
    ② 能控制可以执行的定向操作(向前、向后、第一、最后、绝对位置、相对位置等)
    ③能标记某些列是可编辑的,某些列为不可编辑的
    ④ 规定范围,使游标对创建它的特定请求(如存储过程)或对所有请求可访问
    ⑤ 指示DBMS对检索出的数据(而不是指表中活动数据)进行复制,使数据在游标打开和访问期间不变化
  3. 游标的分类
    (1) 显式游标
    显示游标一次从数据库中提取多行数据
    (2) 隐式游标
    隐式游标一般只从数据库中提取一行数据

9、日志等级
Log4j建议只使用四个级别,优先级从高到低分别是 ERROR(错误)、WARN(警告)、INFO(信息)、DEBUG(调试)

10、数据库锁
1、表级锁:开销小,加锁快,不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发最低。(适用于查询为主,少量按索引条件更新数据的应用,WEB应用)
2、行级锁:开销大,加锁慢;会出现死锁,锁定粒度最小,发生锁冲突的概率最低,并发度也最高。(适用于有大量按索引条件并发更新少量不同数据。)
3、页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁,锁定粒度界于表锁和行锁之间,并发度一般。

框架基础知识

1、SSM $ #区别
使用$相当于使用字符串拼接SQL语句,不会自动加双引号,存在SQL注入风险;使用#相当于使用占位符,有引号,会进行预编译,可以防止SQL注入风险。
2、Spring cloud哪几个组件
五大组件:Eureka实现服务治理、Ribbon主要提供客户侧的软件负载均衡算法、Hystrix断路器,保护系统,控制故障范围、Zuul,api网关,路由,负载均衡等多种作用、Config配置管理。
3、常用的自动注解有哪些?
@Override :用来标识重写方法
@Param用来在DAO层中声明参数的注解方式
@Autowired自动装配用来可以对成员变量、方法和构造函数进行标注
@Transactional事物管理
@RequestMapping用来处理请求地址映射的注解
@Controller映射当前文件为控制层
@Service标注当前类为service层
4、Mybatis一级缓存和二级缓存
首先,缓存是存储在内存中的临时数据
Mybatis的一级缓存是默认开启的它在一个sqlSession会话里面的所有查询操作都会保存在缓存中,一般来说一个请求中的所有增删改查操作都是在同一个sqlSession里面的,所以我们可以认为每个请求都有自己的一级缓存,如果同一个sqlSession会话中2个查询中间有一个insert、update或delete语句,那么之前查询的所有缓存都会清空。因为每次增删改都会改变原来的数据,所有一级缓存必须刷新。
二级缓存是全局的,也就是说;多个请求可以共用一个缓存,二级缓存需要手动开启。两种方式配置二级缓存:1、缓存先放在一级缓存中,当sqlSession会话提交或者关闭时才会将一级缓存刷新到二级缓存中;2、开启二级缓存后,用户查询时,会先去二级缓存中找,找不到在去一级缓存中找;

5、SpringMVC工作原理
首先MVC主要是三层,分别是model模型,即业务逻辑,包含了entity+service+dao;View视图,即展示页面,包括html、jsp;Controller控制器,主要用于接受请求,调用模型,返回视图。其工作原理
1、客户端发送请求到DispatcherServlet
2、DispatcherServlet查询handlerMapping找到处理请求的Controller
3、Controller调用业务逻辑后,返回ModelAndView
4、DispatcherServler查询ModelAndView,找到指定视图
5、视图将结果返回到客户端。

6、Spring AOP原理
AOP 即面向切面编程,简单地说就是将代码中重复的部分抽取出来,在需要执行的时候使用动态代理技术,在不修改源码的基础上对方法进行增强。主要用于处理系统中分布的各个模块的横切关注点(如:事务管理、日志、缓存、拦截器、过滤器等)。其动态代理实现的方式有两种:1、JDK动态代理 (通过反射接受被代理的类,该代理的类必须实现接口,核心是InvocationHandler和Proxy类)2、Cglib动态代理,原理是Cglib通过继承方式实现动态代理。AOP大致作用是降低模块耦合度,使系统项目更容易扩展,规避修改业务代码,更好复用一些重复代码。对于业务的作用有前置通知、后置通知、方法返回后通知、异常通知等。

7、Spring IOC和DI是什么以及区别
IOC是“控制反转”,不是一种技术,只是一种设计思想。
对于控制,传统上我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建和管理对象的全部生命周期。
对于反转,传统上我们自己在对象中主动控制去直接获取依赖对象,也就是正转;
而反转则是由容器来帮忙创建、查找及注入依赖对象,对象只是被动的接受依赖对象。
IOC的底层是对象工厂。
DI即依赖注入是IOC最常见的实现方式,DI实现的方式有属性注入、构造器注入、接口注入三种方式。其中属性注入是setter注入,对应的类中要有private属性、无参构造方法和setter方法;而构造器注入,也叫有参构造方法注入,对应类中需要有参构造方法。

8、@ResponseBody和@RequestBody的区别
1、@ResquestBody是作用在形参列表上,用于将前台发送过来固定格式的数据(xml格式或者json等)封装为对应的JavaBean对象,封装使用到的一个对象时系统默认配置的HttpMessageConverter进行解析,然后封装到形参上。
2、@ResponseBody是作用在方法上的,@ResponseBody表示该方法的返回结果直接写入HTTPresponsebody中,一般在异步获取数据时使用(也就是AJAX),在使用@RequestMapping后,返回值通常解析为跳转路径,但是加上@ResponseBody后返回结果不会被解析为跳转路径,而是直接写入HTTPresponsebody中。

9、Mybatis中namespace有什么作用
在Mybatis中,xml文件中的namespace是用于绑定Dao接口的,即面向接口编程。当namespace绑定接口后,可以不用写接口实现类,Mybatis会通过该绑定自动找到需要执行的SQL语句。

10、Mybatis中有哪些标签?
insert、delete、update、select、if、choose、foreach等

11、SpringBoot启动流程吧
首先从main找到run()方法,在执行run()方法之前new一个SpringApplication对象
进入run()方法,创建应用监听器SpringApplicationRunListeners开始监听
然后加载SpringBoot配置环境(ConfigurableEnvironment),然后把配置环境(Environment)加入监听对象中
然后加载应用上下文(ConfigurableApplicationContext),当做run方法的返回对象
最后创建Spring容器,refreshContext(context),实现starter自动化配置和bean的实例化等工作

中间件

1、Redis
Redis在4.0版本之前是单线程的,之后是支持多线程
Redis数据是存储在内存中的,为了保证Redis数据不丢失,需要把数据从内存存储到磁盘上,以便服务器重启后还能够从磁盘中恢复原有的数据,这就是持久化。三种方式的数据持久化(AOF日志(文本形式,记录操作,写后日志)和RDB快照(二进制文件,记录的是某一时刻的数据)、混合持久化方式)
Redis实现高可用的三种方式:主从复制、哨兵模式、Redis集群
Redis Cluster采用类一致性哈希算法实现节点选择的。
三大特点
1、redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启时可以加载进行使用。
2、Redis不仅仅支持key-value类型的数据,同时提供String、list、set、zset、hash等数据结构的存储。
3、Redis支持数据的备份,即master-slave模式的数据备份
Redis备份方式AOF方式(文本、写后日志、记录操作)、RDB快照方式(二进制文件、记录的是数据)
缓存雪崩、缓存击穿、缓存穿透
缓存雪崩:在某一个时间段,缓存集中过期,或者redis宕机的情况会出现。
例如:在某些热点活动中,会设置某些商品在一个固定的时间内过期,那么在redis里面,这个固定的时间点,大量的key过期,这就导致在这个时间段缓存失效了。
解决办法:
1、将redis做成高可用的:搭建redis集群
2、限流降级:在缓存失效的时候,通过锁的方式来限制访问数据顺序,或 者关掉一些不重要的服务。
3、做数据预热:在正式要上线之前,先将需要访问的数据预先访问一次,这样就可以将大量要访问数据库的数据写到缓存中。
缓存击穿(定点打击):出现缓存击穿的情况是数据量太大,或者是缓存过期了,就是一个key非常热点,大量的访问都打在这个key上面,在key失效的瞬间,所有的请求打在数据库上,就打出了一个洞,击穿了。
解决方案:
1、将热点数据设置不过期,不设置过期时间,就不会出现热点key过期的瞬间造成的问题。
2、加上分布式锁,保证对于每一个key,同时只有一个服务进行访问,其他的服务没有获取到锁,就不能访问redis的这个key,那么就需要等待获取锁。
缓存穿透(穿过redis和数据库):就是用户想要查询一个数据,在redis中查询不到,即没有在缓存中命中,那么就会直接去持久化的mysql中进行查询,发现也没有这个数据,那么本次查询就失败了。
解决方案:
1、使用布隆过滤器(在redis前面拦截数据,减少冲击):布隆过滤器是一种数据结构,对所有可能查询到的参数都是以hash的方式存储,会先在控制层进行校验,不符合的话,则丢弃,这就避免了对底层存储系统的压力
2、缓存空的对象:在数据库中没有查询到期望的数据时,那么就返回一个空对象,并且缓存这个空对象,再对其设置一个过期时间。之后客户端再次访问时,缓存直接访问空对象即可。(这会产生2个问题,缓存非常多的空对象占用内存,空对象过期了,那么压力还是会打到持久化数据库上面,影响数据的一致性业务)

Linux基础知识

1、linux基本常用命令
Vim cat rename ps rename rm mv mkdir find kill tar 等等

Java后端场景题

1、如果一个外卖配送单子要发布,现在有200个骑手都想要接这一单,如何保证只有一个骑手接到单子?
答:
1、如果只是单机,采用volatile关键字修饰该订单采用CAS(compare and swap的缩写,即我们所说的比较交换)操作对其进行乐观锁(悲观锁是将资源锁住,等一个之前获得锁的线程释放锁之后,下一个线程才可以访问。而乐观锁采取了一种宽泛的态度,通过某种方式不加锁来处理资源,比如通过给记录加version来获取数据,性能较悲观锁有很大的提高)操作。
2、如果是多机的话,采用Redis、zookeeper分布式锁加锁。
3、消息队列实现幂等接口(对重复的请求操作执行结果相同的操作叫幂等性,消息队列实现幂等性接口对重复操作进行预防性处理,比如不再执行等)。

2、多个微信用户抢红包
这个和上题一样的道理
3、美团首页每天从10000个商家里面推荐50个商家置顶,每个商家有一个权值。你如何来推荐?第二天怎么更新推荐的商家?
答:可以借鉴下stackoverflow,视频网站等等的推荐算法。
4、1000个任务分给10个人做
答:1、hash 2、创建10个线程,然后用同步锁,Synchornized
5、保证发送消息的有序性,消息处理的有序性。
6、如何把一个文件快速下发到100w个服务器
采用p2p网络形式比如树状形式,网络形式 单个节点既可以从其他结点接收服务又可以向其他结点提供服务。对于树状传递,在100w台服务器这种量级上,可能存在两个问题
1、如果树上的某一个节点坏掉了,那么从这个节点往下的所有服务器全部宕机。
2、如果树中的某条路径,传递时间太长了,使得传递效率退化
改进:100w台服务器相当于100w个节点的连通图。那么我们可以在图里生成多颗不同的生成树,在进行数据下发时,同时按照多颗不同的树去传递数据。这样就可以避免某个中间节点宕机,影响到后续的节点。同时这种传递方法实际上是一种依据时间的广度优先遍历,可以避免某条路径过长造成的效率低下。
7、给每个组分配不同的IP段,怎么设计一种结构使的快速得知IP是哪个组的?
划分子网,添加子网掩码。
8、10亿个数,找出最大的10个。
(1)、单机+单核+足够大内存:维护一个小顶推每一次都与顶堆即最小的数进行比较。如果某一后续元素比容器内最小的数字大,则删除容器内最小元素,并将该元素插入容器。
(2)、单机+多核+足够大内存:这时可以直接在内存中使用Hash方法将数据划分成n个partition,每个partition交给一个线程处理,线程的处理逻辑同(1)类似,最后一个线程将结果归并。
9、有几台机器存储着几亿淘宝搜索日志,你只有一台2g的电脑,怎么选出搜索热度最高的十个
可以拆分成n多个文件,以首字母区分,不同首字母放在不同文件,长度仍过长的继续按照次首字母进行拆分。这样一来,每一个文件的每个数据长度相同且首字母尾字母也相同,就能保证数据被独立分为了n个文件,且各个文件中不存在关键词的交集。对于每个文件、使用hash或者Trie树进行词频统计并用大根堆获取词频最多的10个词。依次处理每个文件,并逐渐更新最大的十个词。
10、分布式集群中如何保证线程安全?Redis、zookeeper的分布式锁来保证。
11、给个淘宝场景,怎么设计-消息队列?(异步处理(用户注册(发送邮件和发送短信))、应用解耦(用户下单购买业务,订单系统和数据库解耦,消息队列存放下单请求,用户不用直接写入数据库)、流量消峰(秒杀或者团购时使用消息队列,用户的请求放入消息队列中如果超过最大数量值则抛弃用户请求跳转到错误页面,队列请求再做后续处理,缓解了服务器的压力)、消息通信(点对点和发布订阅模式)等)
12、10万个数,输出从小到大?
1、多路归并排序算法,在N个数中取M个数排序到内存中,然后多路归并算法进行合并。
2、采用位图标志该数量的个数,标志完成后再遍历bitmap进行排序。
13、有十万个单词,找出重复次数最高十个?
针对top k类问题,通常比较好的方案是{分治+trie树/hash+小顶堆},即先将数据集按照hash方法分解成多个小数据集,然后使用trie树或者hash统计每个小数据集中的query词频,之后用小顶堆求出每个数据集中出现频率最高的前K个数,最后在所有top k中求出最终的top k。类似上面的第8题。
14、在2.5亿个整数中找出不重复的整数,内存不足以容纳这2.5亿个整数
位操作。采用bitmap方法来对每一个数据进行标记。0代表存在,1代表不存在。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值