Java面试题自我总结

1, Java的基本部分

1.1 java中int数据占几个字节
1.2 有了基本类型, 为什么还需要包装类型?
1.3 说一下"=="和equals方法的区别?
1.4 讲一下String和StringBuilder的区别(final)?StringBuffer和StringBuilder的区别?
1.5, 讲一下java中的集合?
1.6 ArrayList和LinkedList的区别和使用场景?
1.7 讲一下HashMap和HashTable的区别? HashTable和 ConcurrentHashMap的区别?
1.8 讲一下线程的几种实现方式? 怎么启动? 怎么区分线程?
1.9 线程池的作用?
1.10 讲一下什么是设计模式? 常用的设计模式有哪些?
1.11 实现一拷贝文件的工具类使用字符流还是字节流?
1.12 final, finally, finalize的区别?
1.13 访问权限修饰符private defualt protected public的区别?
1.14 &和&&的区别?
1.15 在Java中, 如何跳出当前的多重嵌套循环
1.16 重载和重写的区别? 重载的方法能否通过返回类型进行区别?
1.17 java中length,length(),size()区别
1.18接⼝和抽象类的区别是什么?
1.19 Spring @Configuration 和 @Component 区别
1.20 什么是动态代理

2, JavaWeb部分

2.1 http get post请求的区别?
2.2 说一下你对Servlet的理解? 或者Servlet是什么?
2.3 简单说一个Servlet的生命周期?
2.4 Servlet API中的forward() 与redirect() 的区别?
2.5 JSP和Servlet有哪些相同点和不同点?
2.6 jsp有哪些内置对象? 作用分别是什么?
2.7 Session和Cookie的区别和使用场景

3, 数据库部分

3.1 数据库
3.2 jdbc批量插入几百万数据怎么实现?
3.3 简单说一下你对jdbc的理解

4, 前端部分

4.1 简单介绍一下ajax?
4.2 js和jQuery的关系?
4.3 简单说一下html5?
4.4 简单说一下css3?
4.5 bootstrap是什么?

5, 框架部分

5.1 MVC的各个部分都有哪些技术实现
5.2 简单讲一下SpringMVC的执行流程
5.3 说一下Spring中的两大核心
5.4 Mybatis中的resultType和resultMap的区别
5.5 Springboot和SpringMVC的区别?
5.6 Mybatis中的#和$的区别
5.7 @Bean和@Component的区别

6, 高级部分

6.1 有没有做过数据库优化方面的事情?
6.2 MyISAM和INNODB的区别
6.3 索引都有哪些?
6.4. 索引使用小技巧?(非常重要)
6.5 数据库优化之读写分离
6.6 数据库优化之缓存
6.7 jdbc批量插入几百万数据怎么实现?
6.8 有没有使用过redis? redis是什么
6.9 简单说一下redis的使用场景
6.10 什么是反射?
6.11实现一个简单的单例模式
6.12 Redis和Mongodb的区别?
6.13 Redis中的基本类型

7, 线程部分

7.1 什么是线程
7.2 什么是线程安全和线程不安全?
7.3 什么是乐观锁和悲观锁?
7.4 wait()和sleep()的区别?
7.5 synchronized与Lock的区别


1.1 java中int数据占几个字节

java中有几种基本数据类型? 8种
int 占4个字节, 32位
boolean 1位


1.2 有了基本类型, 为什么还需要包装类型?

Java是一个面向对象的语言, 而基本的数据类型, 不具备面向对象的特征
null Integer---->null int----->0


1.3 说一下"=="和equals方法的区别
  1. ==用来判断变量之间的值是否相等. 变量就可以分为基本数据类型变量, 引用类型变量
    如果是基本数据类型的比较的是值, 而如果是引用类型变量要比较对应的引用的内存地址
  2. 使用equals()比较String, File, Date还有其它8种基本类型的封装类时, 比较的是内容
  3. 使用==比较时候, 等号两边数据类型必须一致, 不然编译不通过

1.4 讲一下String和StringBuilder的区别(final)?StringBuffer和StringBuilder的区别?
  1. 在java中提供三个类String StringBuilder StringBuffer 来表示和操作字符串, 字符串就是多个字符的集合.
    String是内容不可变的字符串. String底层使用了一个不可以变的字符数组(final char[])
    String str = new String(“bbb”);
    在这里插入图片描述
    而StringBuilder和StringBuffer是内容可以改变的字符串. StringBuilder StringBuffer底层是使用的可变的数组(没有使用final来修饰)
  1. 最经典就是拼接字符串
    ①, String 进行拼接 String c = “a” + “b” ;
    ②, StringBuilder 或者StringBuffer
    StringBuilder sb = new StringBuilder(); sb.append(“a”).append(“b”);
    拼接字符串不建议使用String进行拼接, 要使用StringBuilder 或者StringBuffer (如果是简单的字符串相加可以使用String连接, 但在循环内部还是老老实实使用另外两个, 因为String相比另外两个比较消耗资源)
  1. StringBuilder是线程不安全的, 效率较高, 而StringBuffer是线程安全的, 效率较低

1.5 讲一下java中的集合?
  1. Java中的集合分为value, key-value(Collection和Map)两种.
  1. 存储值(value)又分List和Set:
    ①, List是有序的, 可以重复的.
    ②, Set是无序的, 不可以重复的. 根据equals和hashCode判断, 也就是说如果一个对象要存储在Set中, 必须重写equals和hashCode方法

1.6 ArrayList和LinkedList的区别和使用场景?
  1. 区别:
    ①ArrayList底层使用的是数组. LinkedList使用的是链表.
    ②数组具有查询特定元素比较快. 而插入和删除比较慢(因为数据在内存中是一块连续的内存, 如果插入或删除是需要移动内存).
    链表是不要求内存是连续的, 在当前元素中存放下一个或上一个元素. 查询时需要从头部开始, 一个一个的找. 所以查询效率低. 插入时不需要移动内存, 只需要改变引用指向即可. 所以插入或删除的效率高
  1. 应用场景:
    ArrayList使用在查询比较多, 但是插入和删除比较少的情况, 而LinkedList使用在查询比较少插入和删除比较多的情况.

1.7 讲一下HashMap和HashTable的区别? HashTable和 ConcurrentHashMap的区别?
  1. 相同点: HashMap和HashTable都可以使用来存储key-value的数据
  2. 区别:
    ①, HashMap是可以把null做为key或者value的, 而HashTable是不可以的.
    ②, HashMap是线程不安全的, 效率较高. 而HashTable是线程安全的, 效率较低.

我想线程安全但我又想效率高?
    ConcurrentHashMap通过将整个Map分为N个Segment(类似HashTable), 可以提供相同的线程安全, 但是效率提升N倍, 默认提升16倍


1.8 讲一下线程的几种实现方式? 怎么启动? 怎么区分线程?
  1. 实现方式
    ①, 通过继承Thread类实现一个线程
    ②, 通过实现Runnable接口实现一个线程
    注: 继承扩展性不强, java只支持单继承, 如果一个类继承Thread就不能继承其他的类了
  1. 怎么启动?
    Thread thread = new Thread(继承了Thread的对象/实现了Runnable的对象)
    thread.start();
    启动线程使用start() 方法, 而启动了以后执行的是run方法.
  1. 怎么区分线程? 一个系统中有很多线程, 每个线程都会打印日志, 我想区分是哪个线程打印的怎么办?
    thread.setName(“设置一个线程名称”); 这是一种规范, 在创建线程完成后, 都需要设置名称.

1.9 线程池的作用?
  1. 限定线程的个数, 不会导致由于线程过多导致系统运行缓慢或崩溃
  2. 线程池不需要每次都去创建或销毁, 节约了资源.
  3. 线程池不需要每次都去创建, 响应时间更快.

1.10 讲一下什么是设计模式? 常用的设计模式有哪些?

设计模式就是经过前人无数次的实践总结出的, 设计过程中可以反复使用的, 可以解决特定问题的设计方法.

  1. 单例(懒汉模式/饿汉模式)
    ①, 构造方法私有化, 让除了自己类中能创建外其他地方不能创建
    ②, 在自己的的类中创建一个实例(懒汉式单例模式在第一次调用的时候进行实例化, 饿汉式单例类:在类初始化时,已经自行实例化。)
    ③, 提供一个方法获取该实例对象(创建时需要进行方法同步)
  2. 工厂模式: Spring IOC就是使用了工厂模式. 也就是对象的创建交给一个工厂去创建.
  3. 代理模式: Spring AOP就是使用的动态代理.

具体地址 Java实现单例模式

1.11 实现一拷贝文件的工具类使用字符流还是字节流?

我们拷贝的文件不确定只包含字符流, 有可以有字节流(图片, 声音, 图像等), 为了考虑到通用性, 要使用字节流


1.12 final, finally, finalize的区别?

final 用于声明属性,方法和类, 分别表示属性不可变, 方法不可覆盖, 类不可继承.
finally 是异常处理语句结构的一部分,表示总是执行.
finalize 是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法


1.13 访问权限修饰符private defualt protected public的区别?

1.14 &和&&的区别?
  1. &运算符有两种用法: ①短路与, ②逻辑与
  2. &&之所以称为短路与是因为, 如果&&左边的表达示值是false, 右边的表达式会直接被短路掉, 不会进行去处. 很多时候我们可能需要&&而不是&, 例如在验证用户登录时判定用户名不是null而且不是空字符串, 应该写成username != null && !username.equals(“”), 二者的顺序不能交换, 更不能使用&运算符, 因为第一个条件如果不成立, 根本不能进行字符串equals的比较, 否则会产生NullPointerException异常. 逻辑或(|)和短路或(||)的差别也是如此

1.15 在Java中, 如何跳出当前的多重嵌套循环
  1. 在最外层循环前加一个标记如A, 然后用break A;可以跳出多重循环.
  2. 使用return跳出循环

1.16 重载和重写的区别? 重载的方法能否通过返回类型进行区别?

方法的重载和重写都是实现多态的方式, 区别在于重载实现的是编译时的多态性, 而重写实现的是运行时的多态性. 重载发生在一个类中, 同名的方法如果不同的参数列表(参数类型不同, 参数个数不同或者二者都不同)则视为重载; 重写发生在子类和父类之间, 重写要求子类被重写方法与父类被重写方法有相同的返回类型, 比父类被重写方法更好访问, 不能比父类被重写声明更多的异常, 重载对返回类型没有特殊的要求

方法重载的规则

  1. 方法名一致, 参数列表中参数的顺序, 类型, 个数不同
  2. 重载与方法返回值无关, 存在父类,子类和同类中
  3. 可以抛出不同的异常, 可以有不同的修饰符

方法重写的规则

  1. 参数列表必须完全和被重写的方法的一致, 返回类型必须完全与被重写方法的返回类型一致
  2. 构造方法不能被重写, 声明final的方法不能被重写, 声明为static的方法不能被重写, 但能能够被再次声明
  3. 访问权限不能比父类中被重写的方法访问权限更低
  4. 不能抛出比父类更新的异常

1.17 java中length,length(),size()区别
  1. java中的length属性是针对数组说的,比如说你声明了一个数组,想知道这个数组的长度则用到了length这个属性.
  2. java中的length()方法是针对字符串String说的,如果想看这个字符串的长度则用到length()这个方法.
  3. .java中的size()方法是针对泛型集合说的,如果想看这个泛型有多少个元素,就调用此方法来查看!

1.18接⼝和抽象类的区别是什么?
  1. 接⼝的⽅法默认是 public,所有⽅法在接⼝中不能有实现(Java 8 开始 接⼝⽅法可以有默认实现),⽽抽象类可以有非抽象的⽅法。
  2. 接⼝中除了static、final变量,不能有其他变量,⽽抽象类中则不⼀ 定。
  3. ⼀个类可以实现多个接⼝,但只能实现⼀个抽象类。接⼝自⼰本身可以通过extends关键字扩展多个接⼝
  4. 接⼝⽅法默认修饰符是public,抽象⽅法可以有public、protected和 default这些修饰符

1.19Spring @Configuration 和 @Component 区别

一句话概括就是 @Configuration 中所有带 @Bean 注解的方法都会被动态代理,因此调用该方法返回的都是同一个实例。
如果是@Component中的类调用@Bean修饰的方法,每次都会创建并返回不同的对象


1.20 什么是动态代理
  1. 动态代理就是,在程序运行期,创建目标对象的代理对象,并对目标对象中的方法进行功能性增强的一种技术。在生成代理对象的过程中,目标对象不变,代理对象中的方法是目标对象方法的增强方法。可以理解为运行期间,对象中方法的动态拦截,在拦截方法的前后执行功能操作。

  2. 静态代理是在程序运行前就写好了代理方法的实现, 如果想对多个类进行静态代理就需要写多个代理对象, 比如我想让每个方法都实现添加日志的操作那需要添加多个代理方法, 后面如果想修改的话也要一起修改, 增加了代码维护复杂度


2.1 http get post请求的区别?
  1. 相同点: get和post请求都是http请求方式, 用户通过不同的http的请求方式完成对资源(url)的不同操作. get,post,put,delete 就对应着对这个资源的查, 改, 增, 删 4个操作, 具体点讲get一般用于获取/查询资源信息, 而post一般用于更新资源信息
  2. 区别:
    ①, get请求提交的数据会在地址栏显示出来, 而post请求不会再地址栏显示出来
    ②, 传输数据的大小(get请求由于浏览器对地址长度的限制而导致传输的数据有限制, 而post不会)
    ③, 安全性, post的安全性要比get的安全性高

2.2 说一下你对Servlet的理解? 或者Servlet是什么?
  1. Servlet (Server Applet), 全称Java Servlet, 用Java编写的服务器端程序, 而这些程序(Servlet)都要实现Servlet这个接口. 其主要功能是用于交互地浏览和修改数据, 生成动态Web内容. Servlet运行于支持Java的应用服务器中.
  2. 实际工作中我们是继承HttpServlet, 重写doGet和doPost方法或者你也可以重写service方法完成对get和post请求的响应

2.3 简单说一个Servlet的生命周期?

Servlet有良好的生存期的定义, 包括加载实例化, 初始化, 处理请求以及服务结束. 这个生存期由Servlet接口的init service 和destroy方法表达

加载Servlet的class–> 实例化Servlet–> 调用Servlet的init完成初始化–> 响应请求(Servlet的service方法) --> Servlet容器关闭时(Servlet的destory方法)

Servlet启动时, 开始加载Servlet, 生命周期开始. Servlet被服务器实例化后, 容器运行其init方法, 请求到达时运行其service方法, servcie方法自动派遣运行与请求对应的doXXX方法(doGet, doPost)等,当服务器决定将实例销毁的时候(服务器关闭)调用destory方法


2.4 Servlet API中的forward() 与redirect() 的区别?
  1. forward是服务器端的转向而redirect是客户端的跳转.
  2. 使用forward浏览器不会发生改变, 而redirect会发生改变.
  3. forward是一次请求中完成, 而redirect是重新发起请求.
  4. forward是由服务端完成,而不是客户端重新发起的请求, 效率较高

2.5 JSP和Servlet有哪些相同点和不同点?
  1. 相同点: JSP是Servlet技术的技术扩展, 所有的jsp文件都会翻译为一个继承HttpServlet的类. 也就是JSP最终也是一个Servlet, 这个Servlet对外提供服务.
  2. 不同点:
    ①, Servlet和JSP最主要的不同点是JSP侧重于视图, Servlet主要用于控制逻辑
    ②, Servlet如果要实现html功能, 必须使用Writer输出对应的html, 比较麻烦. 而JSP的情况是Java和html 可以组合成一个扩展名为.jsp的文件, 做界面展示比较方便而嵌入逻辑比较复杂.

2.6 jsp有哪些内置对象? 作用分别是什么?

9个内置对象:
request 用户请求, 此请求会包含来自GET/POST请求的参数
② response 网页传回用户端的响应
pageContext 网页的属性是在这里管理
session 与请求有关的会话
application servlet正在执行的内容
⑥ out 用来传送回应的输出
⑦ config servlet的构架部件
⑧ page JSP网页本身
⑨ exception 针对错误网页, 未捕捉的例外
四大作用域: request pageContext session application 可以通过jstl从四大作用域中取值
Jsp传值 request session application cookie都可以传值


2.7 Session和Cookie的区别和使用场景

相同点: Session和Cookie都是会话(Session)跟踪技术. Cookie通过在客户端记录信息确定用户身份, Session通过在服务器端记录信息确定用户身份. 但是Session的实现依赖Cookie. sessionId(session的唯一标识需要存放客户端)

不同点:
①, Cookie数据存放在客户端的浏览器上, Session数据存放在服务器上
②, Cookie不是很安全, 别人可以分析存入在本地的Cookie并进行Cookie欺骗, 考虑到安全问题应当使用Session
③, Session会在一定时间内保存在服务器上. 当访问增多, 会比较占用你服务器的性能, 考虑到减轻服务器性能方面, 应当使用Cookie
④, 单个Cookie保存的数据不能超过4K, 很多浏览器都限制一个站点最多保存20个cookie
⑤, 所以个人建议: 将登录信息等重要信息存入在Session中, 其他信息如果需要保留, 可以放到Cookie中

应用场景: 购物车最好使用Cookie, 但是Cookie是可以在客户端禁用的, 这时候我们要使用Cookie+数据库的方式实现, 当Cookie中不能取出数据时, 就从数据库中获取


3.1 数据库
  1. 数据库的分类及常用的数据库
    数据库分为:关系型数据库和非关系型数据库
    关系型: mysql, oracle, sqlserver等
    非关系型: redis, memcache, mogodb, hadoop等

3.3 简单说一下你对jdbc的理解

JDBC(Java Database Connection)API, 即Java数据库编程接口, 数据库管理系统(mysql oracle)等很多, 每个数据库管理系统支持的命令是不一样的
Java只定义接口, 让数据库厂商自己实现接口, 对于我们开发者而言, 只需导入对应厂商开发的实现即可, 然后以接口方式进行调用(mysql + mysql驱动(实现) + jdbc)
在这里插入图片描述


4.1 简单介绍一下ajax?
  1. 什么是ajax?
    异步的javascript和xml
  2. 作用是什么?
    通过ajax与服务器进行数据交换, ajax可以使网页实现布局更新. 这意味着可以在不重新加载整个页面的情况下, 对网页的某个部分进行更新
  3. 怎么实现ajax
    XmlHttpRequest对象, 使用这个对象可以异步向服务器发送请求, 获取响应, 完成局部更新. open send responseText/responseXML局部响应
  4. 使用场景
    登录失败时不跳转页面, 注册时提示用户名是否存在, 二级联运等等场景

4.2 js和jQuery的关系?

jQuery是一个js框架, 封装了js的属性和方法, 让用户使用起来更加便利, 并且增强了js的功能
使用原生js是要处理很多兼容性的问题(注册事件等), 由jQuery封装了底层, 就不用处理兼容性问题
原生的js的dom和事件绑定和ajax等操作非常麻烦, jQuery封装以后操作非常方便


4.3 简单说一下html5?

html5是最新版本的html, 是在原来的html4的基础上增强了一些标签
html5增加了一些像画板, 声音, 视频, web存储等高级功能. 但是html5有一个不好的地方就是html5太强调语义了, 导致开发中都不知道要选择哪个标签
例如:在做页面布局时, 无论头部, 主题, 导航等模块都使用div来表示, 但是html5的 规范, 需要使用不同的标签来表示.(header, footer等)


4.4 简单说一下css3?

css3是最新版本的css是对css2的功能增强
css3中提供一些原来css2中实现起来比较困难或者不能实现的功能
1, 盒子圆角边框
2, 盒子和文字的阴影
3, 渐变
4, 转换, 移动, 缩放, 旋转等
5,过渡, 动画都可以实现动画
6, 可以使用媒体查询实现响应式网站
css3的最大缺点就是要根据不同的浏览器处理兼容性. 对应有一些处理兼容性的工具, 不用担心


4.5 bootstrap是什么?

bootstrap是一个移动设备优先的UI框架. 我们可以不用写任何css, js代码就能实现比较漂亮的交互性的页面. 我们程序员对页面的编写是有感伤的, 所以要自己写页面的话就要使用类似bootstrap这样的UI框架

平时用得很多的:
1, 模态框
2, 表单, 表单项
3, 布局
4, 删格系统


5.1 MVC的各个部分都有哪些技术实现

M(Model) 模型 javabean
V(View) 视图 html jsp freemaker
C(Controller) 控制器 Servlet Action

MVC模式的目的就是实现Web系统的职能分工。 Model层实现系统中的业务逻辑,通常可以用JavaBean或EJB来实现。 View层用于与用户的交互,通常用JSP来实现。 Controller层是Model与View之间沟通的桥梁,它可以分派用户的请求并选择恰当的视图以用于显示,同时它也可以解释用户的输入并将它们映射为模型层可执行的操作。


5.2 简单讲一下SpringMVC的执行流程
  1. 用户向服务器发送请求, 请求被Spring前端控制器DispatcherServlet捕获
  2. DispatcherServlet对请求URL进行解析, 得到请求资源标识符(URL). 然后根据该URL调用HandlerMapping获取该Handler配置的所有对象(包括Handler对象以级Handler对象对应的拦截器) , 最后以HandlerExecutionChain对象的形式返回 (查找handler)
  3. DispathcerServlet根据获取的Handler, 选择一个合适的HandlerAdapter, 提取Requset中的模型数据, 填充Handler入参, 开始执行Handler(Controller), Handler执行完成后, 向DispatcherSerlvet返回一个ModelAndView对象(执行handler)
  4. DispatcherSerlvet根据返回的ModelAndView, 选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)(选择ViewResovler)
  5. 通过ViewResolver结合Model和View, 来渲染视图, DispatcherServlet将渲染结果返回给客户端(渲染返回)

快速记忆技巧:
核心控制器捕获请求, 查找Handler, 执行Handler, 选择ViewResolver, 通过ViewResolver渲染视图并返回


5.3 说一下Spring中的两大核心

Spring是什么?
Spring是JavaEE应用程序框架, 是轻量级的IOC和AOP的容器框架, 主要是针对javaBean的生命周期进行管理的轻量级容器, 可以单独使用, 也可以和Struts框架, ibatis框架等组合使用.

  1. IOC(Inversion of Control) 或DI(Dependency Injection)
    IOC控制权反转
    原来我Service需要调用Dao, Service就需要new一个Dao, 使用IOC就可以让Spring帮我创建
    核心原理: 就是配置文件 + 反射(工厂也可以) + 容器(map)
  2. AOP: 面向切面编程
    核心原理: 使用动态代理的设计模式执行方法前后或出现异常加入相关逻辑
    我们主要使用AOP来做:
    ①, 事务处理: 执行方法前, 开启事务, 执行完成后关闭事务, 出现异常后回滚事务
    ②, 权限判断: 在执行方法前, 判断是否具有权限
    ③, 日志: 在执行前进行日志处理
    ④, …

5.4 Mybatis中的resultType和resultMap的区别?
  1. resultType是直接表示返回类型的,对应我们model对象的中实体
  2. resultMap则是里要提前定义数据库和实体之间的映射key-value的关系, 并且resultType和resultMap不能同时存在

5.5 Springboot和SpringMVC的区别?

SpringBoot不是SpringMVC的替代,SpringMVC是一个MVC框架,SpringBoot是一个简化Spring开发的工具,这两个东西没有直接的关联, 唯一的关联可能就是当运用SpringBoot之后,SpringMVC的配置会发生一些改变,SpringBoot简化了配置和简化了依赖


5.6 Mybatis中的#和$的区别?
  1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by “111”, 如果传入的值是id,则解析成的sql为order by “id”.
  2. $将传入的数据直接显示生成在sql中。如:order by u s e r i d user_id userid,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id.
  3. #方式能够很大程度防止sql注入。
  4. $方式无法防止Sql注入。
  5. $方式一般用于传入数据库对象,例如传入表名.
  6. 一般能用#的就别用$.

5.7 @Bean和@Component的区别
  1. 注解作用
    @Component注解表明一个类会作为组件类, 并告诉Spring要为这个类创建Bean
    @Bean注释告诉Spring这个方法将会返回一个对象, 这个对象要注册为Spring应用上下文中的Bean, 通常方法体中包含了最终产生Bean实例的逻辑
  1. 两者对比
    相同点: 两者的结果都是为Spring容器注册Bean
    不同点:
    @Component通常是通过类路径扫描来自动侦测及自动装配到Spring容器中
    @Bean注解通常是我们在标有该注解的方法中定义这个Bean的逻辑
  1. 理解
    @Component(@Controller @Service @Responsitory) 作用于类上, 只有在我们SpringBoot程序启动了组件扫描并且被注释的类时才有效. 通过组件扫描, Spring将扫描整个类路径, 并将所有@Component注释类添加到Spring Context, 这里有的不足就是会把整个类当作Bean注册到Spring容器中, 如果这个类并不是所有方法都要注册到Bean的话, 会出现不需要方法都注册成为了Bean, 这时候必须确保这些不需要的方法也能注册为Bean或者在扫描中加filter过滤这些不需要的Bean, 否则Spring将无法启动成功

    @Bean相对来说就更加灵活了, 它可以独立加在方法或者类上, 按需注册到Spring容器, 而且如果你要用到第三方类库里面面某个类或者方法的时候, 你就只能用@Bean把这个类或者方法注册到Spring容器, 因为用@Component你需要配置组件扫描到这个第三方类路径而且还在要别人的源代码上加上这个注解, 很明显是不现实的

6.1 有没有做过数据库优化方面的事情?
  1. 定位: 查询, 定位慢查询
  2. 优化手段
    ①, 创建索引: 创建合适的索引, 我们就可以先在索引中查询, 查询到以后直接找对应的记录
    ②, 分表: 当一张表的数据比较多或者一张表中的某些字段的值比较多并且很少使用时, 采用水平分表和垂直分表来优化
    ③, 读写分离: 当一台服务器不能满足需求时, 采用读写分离的方式进行集群处理
    ④, 缓存: 使用redis来进行缓存

6.2 MyISAM和INNODB的区别
  1. 事务安全: myisam不支持事务和innodb支持
  2. 查询和添加速度: myisam不用支持事务就不用考虑同步锁, 查找和添加的速度快
  3. 支持全文索引: myisam支持innodb不支持
  4. 锁机制: myisam支持表锁而innodb支持行锁(事务)
  5. 外键: myisam不支持外键, innodb支持外键

6.3 索引都有哪些?

什么是索引: 数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。

分类: 普通索引/唯一索引/主键索引/全文索引

普通索引: 允许重复值的出现
唯一索引: 除了不能有重复的记录外, 其它和普通索引一样(用户名, 用户身份证, email, tel)
主键索引: 是随着设定主键而创建的, 也就是把某个列设为主键的时候, 数据库就会给该列创建索引, 这就是 主键索引, 唯一且没有null值
全文索引: 用来对表中的文本域(char, varchar, text) 进行索引, 全文索引针对myisam
explain select * from articles where match(title, body) against(‘database’);[这样才会使用全文索引]


6.4 索引使用小技巧?(非常重要)

索引弊端

  1. 占用磁盘空间
  2. 对插入, 修改, 删除操作有影响, 变慢

使用场景:

  1. 肯定在where条件经常使用, 如果不做查询就没有意义
  2. 该字段的内容不是唯一的几个值
  3. 字段内容不是频繁变化

具体技巧

  1. 对于创建的复合索引(多列表索引), 不是使用的第一部分就不会使用索引
    在这里插入图片描述
  2. 对于使用like查询, 查询如果是’%aaa’ 不会使用到索引而’aaa%’ 会使用到索引
    在这里插入图片描述
    所以在使用like查询时, '关键字’的最前面不能使用%或_这样的字符, 如果一定要前面有变化的值, 则考虑使用全文索引框架 sphinx
  3. 如果条件中有or, 有条件没有使用索引, 即使其中有条件带索引也不会使用. 换言之, 就是要求使用的字段必须单独使用索引.
  4. 如果列类型是字符串, 那一定要在条件中将数据使用引号引用起来, 否则不使用索引.
    在这里插入图片描述
    也是就是, 如果列是字符串类型, 无论是字符串还是数字就一定要用’'把它包括起来
  5. 如果mysql使用全表扫描比使用索引快, 则不使用索引 .(表里面只有一条记录)
  6. 使用update或者delete进行操作语句时如果where条件里字段都为索引字段, 则行锁, 否则表锁

6.5 数据库优化之读写分离

一台数据库支持的最大并发连接数是有限的, 如果用户并发访问太多. 一台服务器满足不了要求是可以使用集群处理, mysql的集群处理技术最常用的就是读写分离.

  1. 主从同步
    数据库最终会把数据持久化到磁盘, 如果集群必须确保每个数据库服务器的数据是一致的. 将能改变数据库数据的操作都往主数据库去写, 而其他的数据库从主数据库上同步数据
  2. 读写分离
    使用负载均衡来实现写的操作都往主数据库去, 而读的操作往从数据库去

6.6 数据库优化之缓存

在持久层(dao)和数据库(db)之间添加一个缓存层, 如果用户访问的数据已经缓存起来时, 在用户访问时直接从缓存中获取, 不用访问数据库. 而缓存是在操作内存的, 访问速度快.

作用: 减少数据库服务器压力, 减少访问时间

Java中的常用缓存:

  1. hibernate的二级缓存, 该缓存不能完分布式缓存.
  2. 可以使用redis(memcahe等)来作为中央缓存, 对缓存数据时行集中处理

6.7 jdbc批量插入几百万数据怎么实现?
  1. 变多次提交为一次
  2. 使用批量操作

    省出的时间可观
    像这样的批量插入操作能不使用代码操作就不使用, 可以使用存储过程来实现

6.8 有没有使用过redis? redis是什么
  1. redis是一个key-value的nosql数据库, 先存到内存中, 会根据一定的策略持久化到磁盘, 即使断电也不会丢失数据. 支持的数据类型比较多
  1. 主要是用来做缓存数据库的数据和web集群时当做中央缓存存放session

6.9 简单说一下redis的使用场景
  1. 缓存:
    把经常需要查询的, 很少修改的数据, 放到读速度很快的空间(内存), 以便下次访问减少时间. 减少压力, 减少访问时间
  2. 计数器
    redis中的计数器是原子性的内存操作, 可以解决库存溢出问题, 进销存系统溢出
  3. session缓存服务器
    web集群时作为session缓存服务器
  4. 缓存队列等

6.10 什么是反射?

反射就是动态加载对象, 并对对象进行进行剖析. 在运行状态下, 对于任意一个类, 都能知道这个类的所有属性和方法, 对于任意一个对象, 都能调用它的任意一个方法, 这种动态获取信息以级动态调用对象的方法功能称为Java反射机制

  1. 优点:
    反射提高了程序的灵活性和扩展性, 在底层框架中用的比较多, 业务层面的开发过程尽量少用
  2. 缺点
    性能不好, 反射是一种解释性操作, 用于字段和方法接入时要远慢于直接代码,.

6.11 实现一个简单的单例
//饥汉模式,线程不安全
public class Singleton {  

    private Singleton (){}  

    private static Singleton instance;  
  
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}  

6.12 Redis和Mongodb的区别

就Redis和MongoDB来说,大家一般称之为Redis缓存、MongoDB数据库。这也是有道有理有根据的
Redis主要把数据存储在内存中,其“缓存”的性质远大于其“数据存储“的性质,其中数据的增删改查也只是像变量操作一样简单;
MongoDB却是一个“存储数据”的系统,增删改查可以添加很多条件,就像SQL数据库一样灵活


6.13 Redisr 基本类型

Redis 支持五种数据类型:string(字符串),hash(哈希), list( 列表),set(集合)及 Zset:(有序集合)。

7.1 什么是线程

线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位,可以使用多线程对运算提速。

进程和线程的根本区别是进程是操作系统资源分配的基本单位,⽽线
程是处理器任务调度和执⾏的基本单位。

比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒


7.2 什么是线程安全和线程不安全?

线程安全: 就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问,直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。

线程不安全:就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据


7.3 什么是乐观锁和悲观锁?

悲观锁
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。

乐观锁
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。

7.4 wait()和sleep()的区别?
  1. sleep是Thread类的方法,wait是Object类中定义的方法. 尽管这两个方法都会影响线程的执行行为,但是本质上是有区别的。sleep()不会导致锁行为的改变,如果当前线程是拥有锁的,那么sleep()不会让线程释放锁, 可以简单认为和锁相关的方法都定义在Object类中,因此调用sleep()是不会影响锁的相关行为
  2. sleep()和wait()都会暂停当前的线程,对于CPU资源来说,不管是哪种方式暂停的线程,都表示它暂时不再需要CPU的执行时间, 区别是,调用wait()后,需要执行notify/notifyAll才能够重新去竞争同步资源锁, sleep()到时间自动恢复
  3. sleep()方法可以任何地方使用, wait方法只能在同步方法或同步块中使用

7.5 synchronized与Lock的区别

在这里插入图片描述
具体可以参数https://blog.csdn.net/u012403290/article/details/64910926

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值