Java 面试合集(2024版)

打印 上一主题 下一主题

主题 1875|帖子 1875|积分 5625


种自己的花,爱自己的宇宙

目录
第一章-Java根本篇
1、你是怎样理解OOP面向对象??? 难度系数:?
2、重载与重写区别??? 难度系数:?
3、接口与抽象类的区别??? 难度系数:?
4、深拷贝与浅拷贝的理解??? 难度系数:?
5、sleep和wait区别 ???难度系数:?
6、什么是自动拆装箱? int和Integer有什么区别??? 难度系数:?
7、==和equals区别??? 难度系数:?
8、String能被继续吗 为什么用final修饰??? 难度系数:?
9、String buffer和String builder区别??? 难度系数:?
10、final、finally、finalize??? 难度系数:?
11、Object中有哪些方法??? 难度系数:?
12、说一下聚集体系??? 难度系数:?
13、ArrarList和LinkedList区别??? 难度系数:???
14、HashMap底层是 数组+链表+红黑树,为什么要用这几类结构??? 难度系数:??
15、HashMap和HashTable区别??? 难度系数:?
16、线程的创建方式??? 难度系数:?
17、线程的状态转换有什么(生命周期)?? 难度系数:?
18、Java中有几种范例的流??? 难度系数:?
19、请写出你最常见的5个RuntimeException??? 难度系数:?
20、谈谈你对反射的理解??? 难度系数:?
21、什么是 java 序列化,如何实现 java 序列化??? 难度系数:?
22、Http 常见的状态码??? 难度系数:?
23、GET 和POST 的区别??? 难度系数:?
24、Cookie 和Session 的区别??? 难度系数:?
第二章-Java高级篇
1、HashMap底层源码??? 难度系数:???
2、JVM内存分哪几个区,每个区的作用是什么??? 难度系数:??
3、Java中垃圾网络的方法有哪些??? 难度系数:?
4、如何判断一个对象是否存活(或者GC对象的判断方法)??? 难度系数:?
5、什么环境下会产生StackOverflowError(栈溢出)和OutOfMemoryError(堆溢出)怎么排查??? 难度系数:??
6、什么是线程池,线程池有哪些(创建)??? 难度系数:?
7、为什么要利用线程池??? 难度系数:?
8、线程池底层工作原理??? 难度系数:?
9、ThreadPoolExecutor对象有哪些参数 怎么设定核心线程数和最大线程数 拒绝计谋有哪些??? 难度系数:?
10、常见线程安全的并发容器有哪些??? 难度系数:?
11、Atomic原子类了解多少 原理是什么??? 难度系数:?
12、synchronized底层实现是什么 lock底层是什么 有什么区别??? 难度系数:???
13、了解ConcurrentHashMap吗 为什么性能比HashTable高,说下原理??? 难度系数:??
14、ConcurrentHashMap底层原理??? 难度系数:???
15、了解volatile关键字不??? 难度系数:?
16、synchronized和volatile有什么区别??? 难度系数:??
17、Java类加载过程??? 难度系数:?
18、什么是类加载器,类加载器有哪些? 难度系数:?
19、简述java内存分配与采取计谋以及Minor GC和Major GC(full GC)??? 难度系数:??
20、如何查看java死锁??? 难度系数:?
21、Java死锁如何制止??? 难度系数:?
第三章-java框架篇
1、简朴的谈一下SpringMVC的工作流程??? 难度系数:?
2、说出Spring或者SpringMVC中常用的5个注解??? 难度系数:?
3、简述SpringMVC中如何返回JSON数据??? 难度系数:?
4、谈谈你对Spring的理解??? 难度系数:?
5、Spring中常用的设计模式??? 难度系数:?
6、Spring循环依赖问题??? 难度系数:??
常见问法
什么是循环依赖?
两种注入方式对循环依赖的影响?
相关概念
三级缓存
四个关键方法
debug源代码过程
总结
其他衍生问题
7、介绍一下Spring bean 的生命周期、注入方式和作用域??? 难度系数:?
8、请描述一下Spring 的事务管理??? 难度系数:?
9、MyBatis中 #{}和${}的区别是什么??? 难度系数:?
10、Mybatis 中一级缓存与二级缓存??? 难度系数:?
11、MyBatis如何获取自动天生的(主)键值??? 难度系数:?
12、简述Mybatis的动态SQL,列出常用的6个标签及作用??? 难度系数:?
13、Mybatis 如何完成MySQL的批量操纵??? 难度系数:?
14、谈谈怎么理解SpringBoot框架??? 难度系数:??
15、Spring Boot 的核心注解是哪个 它重要由哪几个注解构成的??? 难度系数:?
16、Spring Boot自动设置原理是什么??? 难度系数:?
17、SpringBoot设置文件有哪些 怎么实现多环境设置??? 难度系数:?
18、SpringBoot和SpringCloud是什么关系??? 难度系数:?
19、SpringCloud都用过哪些组件 介绍一下作用??? 难度系数:?
20、Nacos作用以及注册中心的原理??? 难度系数:??
21、Feign工作原理??? 难度系数:??
第四章-MySQL
1、Select 语句完整的执行顺序??? 难度系数:?
2、MySQL事务??? 难度系数:??
3、MyISAM和InnoDB的区别??? 难度系数:?
4、灰心锁和乐观锁的怎么实现??? 难度系数:??
5、聚簇索引与非聚簇索引区别??? 难度系数:??
6、什么环境下mysql会索引失效??? 难度系数:?
7、B+tree 与 B-tree区别??? 难度系数:??
8、以MySQL为例Linux下如何排查问题??? 难度系数:??
9、如何处理慢查询??? 难度系数:??
10、数据库分表操纵??? 难度系数:?
11、MySQL优化??? 难度系数:?
12、SQL语句优化案例??? 难度系数:?
13、你们公司有哪些数据库设计规范??? 难度系数:?
14、有没有设计过数据表?你是如何设计的??? 难度系数:?
15、常见面试SQL??? 难度系数:?
第五章-Redis
1、介绍下Redis Redis有哪些数据范例??? 难度系数:???
2、Redis提供了哪几种持久化方式??? 难度系数:???
3、Redis为什么快??? 难度系数:???
4、Redis为什么是单线程的??? 难度系数:???
5、Redis服务器的的内存是多大??? 难度系数:???
6、为什么Redis的操纵是原子性的,怎么保证原子性的??? 难度系数:???
7、Redis有事务吗??? 难度系数:???
8、Redis数据和MySQL数据库的划一性如何实现??? 难度系数:??
9、缓存击穿,缓存穿透,缓存雪崩的原因和办理方案(或者说利用缓存的过程中有没有遇到什么问题,怎么办理的)??? 难度系数:??
10、哨兵模式是什么样的??? 难度系数:??
11、Redis常见性能问题和办理方案??? 难度系数:?
12、MySQL里有大量数据,如何保证Redis中的数据都是热点数据??? 难度系数:??
13、Redis集群方案应该怎么做 都有哪些方案??? 难度系数:??
14、说说Redis哈希槽的概念??? 难度系数:??
15、Redis有哪些适合的场景??? 难度系数:?
16、Redis在项目中的应用??? 难度系数:?
第六章-分布式技能篇
第七章-Git
1、工作中git开辟利用流程(命令版描述)
开辟一个新功能流程: (master线上分支,dev测试分支)
2、Reset 与Rebase,Pull 与 Fetch 的区别
3、git? merge和git rebase的区别
4、git如何办理代码冲突
5、项目开辟时git分支环境
第八章-Linux
1、Linux常用命令
2、如何查看测试项目标日志
3、如何查看最近1000行日志
4、Linux中如何查看某个端口是否被占用
5、查看当前所有已经利用的端口环境
第九章-电商项目篇之尚品汇商城
1、介绍下最近做的项目
1.1 项目背景:
1.2 项目功能:
1.3 技能栈:
1.4 自己负责的功能模块:
1.5 项目介绍参考:
1.6 项目架构图:
1.7 团体业务介绍:
1.8 背景管理系统功能:
1.8.1 背景主页:?
1.8.2 商品模块:?
1).商品管理:
2).商品分类管理:
3).商品平台属性管理:
4).品牌管理:
5).商品评论管理:
1.8.3 销售模块:?
1).促销秒杀管理:
2).礼券、积分管理:
3).关联/保举管理:
1.8.4 订单模块:?
1).订单管理:
2).付出:
3).结算:
1.8.5 库存模块:?
1).库存管理:
2).查看库存明细纪录。?
3).备货/发货:
4).退/换货:
1.8.6 内容模块:?
1).内容管理:
2).广告管理:
3).可自由设置商城导航栏目以及栏目内容、栏目链接。
1.8.7 客户模块:?
1).客户管理:
2).反馈管理:
3).消息订阅管理:
4).会员资格:
1.8.8 系统模块:?
1).安全管理:
2).系统属性管理:
3).运输与区域:
4).付出管理:
5).包装管理:
6).数据导入管理:
1.8.9 报表模块:?
2、项目开辟周期:
3、项目到场人数:
4、公司开辟相关各岗位职责:
4.1 项目司理(PM):
4.2 产品(PD):
4.3 界面设计(UI):
4.4 开辟组长(TL):
4.5 测试(QA):
4.6 运维(SRE):
5、项目开辟流程:
5.1 需求分析
5.2 系统设计
5.3 编码开辟
5.4 系统测试
5.5 摆设实施
6、项目版本控制:
7、一样寻常项目服务器数量:
开辟测试阶段:
生产环境:
8、上线后QPS并发量,用户量、同时在线人数并发数等问题:
9、你们项目标微服务是怎么拆分的,拆分了多少?
10、如何办理并发问题的?
11、如何保证接口的幂等性?
12、你们项目中有没有效到什么设计模式?
13、生产环境出问题,你们是怎么排查的?
14、你做完这个项目后有什么收获?
15、在做这个项目标时间你遇到了哪些问题?你是怎么办理的?
第十章-数据结构和算法
1、怎么理解时间复杂度和空间复杂度
2、数组和链表结构简朴对比
3、怎么遍历一个树
4、冒泡排序(Bubble Sort)
5、快速排序(Quick Sort)
6、二分查找(Binary Search)
1、你所知道的设计模式有哪些
2、单例模式(Binary Search)
2.1 单例模式界说
2.2 单例模式的特点
2.3 单例的四大原则
2.4 实现单例模式的方式
1)饿汉式(立即加载):
2)懒汉式(延迟加载):
3)同步锁(办理线程安全问题):
4)双重查抄锁(提高同步锁的服从):
5)?静态内部类:
6)内部罗列类实现(防止反射和反序列化攻击):
3、工厂设计模式(Factory)
3.1 什么是工厂设计模式?
3.2 简朴工厂(Simple Factory)
3.3 工厂方法(Factory Method)
3.4 抽象工厂(Abstract Factory)
3.5 三种工厂方式总结
4、署理模式(Proxy)
4.1 什么是署理模式?
4.2 为什么要用署理模式?
4.3 有哪几种署理模式?
4.4 静态署理(Static Proxy)
4.5 JDK动态署理(Dynamic Proxy)
4.6 CGLib动态署理(CGLib Proxy)
4.7 简述动态署理的原理, 常用的动态署理的实现方式


第一章-Java根本篇

1、你是怎样理解OOP面向对象 难度系数:

面向对象是利于语言对实际事物进行抽象。面向对象具有以下特征:

  • 继续**:**继续是从已有类得到继续信息创建新类的过程
  • 封装:封装是把数据和操纵数据的方法绑定起来,对数据的访问只能通过已界说的接口
  • 多态性:多态性是指答应不同子范例的对象对同一消息作出不同的响应
2、重载与重写区别 难度系数:


  • 重载发生在本类,重写发生在父类与子类之间
  • 重载的方法名必须相同,重写的方法名相同且返回值范例必须相同
  • 重载的参数列表不同,重写的参数列表必须相同
  • 重写的访问权限不能比父类中被重写的方法的访问权限更低
  • 构造方法不能被重写
3、接口与抽象类的区别 难度系数:


  • 抽象类要被子类继续,接口要被类实现
  • 接口可多继续接口,但类只能单继续
  • 抽象类可以有构造器、接口不能有构造器
  • 抽象类:除了不能实例化抽象类之外,它和普通Java类没有任何区别
  • 抽象类:抽象方法可以有public、protected和default这些修饰符、接口:只能是public
  • 抽象类:可以有成员变量;接口:只能声明常量
4、深拷贝与浅拷贝的理解 难度系数:

深拷贝和浅拷贝就是指对象的拷贝,一个对象中存在两种范例的属性,一种是根本数据范例,一种是实例对象的引用。

  • 浅拷贝是指,只会拷贝根本数据范例的值,以及实例对象的引用地址,并不会复制一份引用地址所指向的对象,也就是浅拷贝出来的对象,内部的类属性指向的是同一个对象
  • 深拷贝是指,既会拷贝根本数据范例的值,也会针对实例对象的引用地址所指向的对象进行复制,深拷贝出来的对象,内部的类执行指向的不是同一个对象
5、sleep和wait区别 难度系数:


  • sleep方法
属于Thread类中的方法
开释cpu给别的线程 不开释锁资源
sleep(1000) 等待高出1s被唤醒

  • wait方法
属于Object类中的方法
开释cpu给别的线程,同时开释锁资源
wait(1000) 等待高出1s被唤醒
wait() 不停等待须要通过notify或者notifyAll进行唤醒
wait 方法必须配合 synchronized 一起利用,不然在运行时就会抛出IllegalMonitorStateException异常
Java
6、什么是自动拆装箱 int和Integer有什么区别 难度系数:

根本数据范例,如int,float,double,boolean,char,byte,不具备对象的特征,不能调用方法。

  • 装箱:将根本范例转换成包装类对象
  • 拆箱:将包装类对象转换成根本范例的值
java为什么要引入自动装箱和拆箱的功能?重要是用于java聚集中,List list=new ArrayList();
list聚集如果要放整数的话,只能放对象,不能放根本范例,因此须要将整数自动装箱成对象。
**实现原理:**javac编译器的语法糖,底层是通过Integer.valueOf()和Integer.intValue()方法实现。
区别:

  • Integer是int的包装类,int则是java的一种根本数据范例
  • Integer变量必须实例化后才能利用,而int变量不须要
  • Integer实际是对象的引用,当new一个Integer时,实际上是天生一个指针指向此对象;而int则是直接存储数据值
  • Integer的默认值是null,int的默认值是0
7、==和equals区别 难度系数:


  • ==
如果比力的是根本数据范例,那么比力的是变量的值
如果比力的是引用数据范例,那么比力的是地址值(两个对象是否指向同一块内存)

  • equals
如果没重写equals方法比力的是两个对象的地址值
如果重写了equals方法后我们往往比力的是对象中的属性的内容
equals方法是从Object类中继续的,默认的实现就是利用==
8、String能被继续吗 为什么用final修饰 难度系数:


  • 不能被继续,因为String类有final修饰符,而final修饰的类是不能被继续的。
  • String 类是最常用的类之一,为了服从,禁止被继续和重写。
  • 为了安全。String 类中有native关键字修饰的调用系统级别的当地方法,调用了操纵系统的 API,如果方法可以重写,可能被植入恶意代码,破坏程序。Java 的安全性也体现在这里。
9、String buffer和String builder区别 难度系数:


  • StringBuffer 与 StringBuilder 中的方法和功能完全是等价的,
  • 只是StringBuffer 中的方法大都采用了 synchronized 关键字进行修饰,因此是线程安全的,而 StringBuilder 没有这个修饰,可以被以为是线程不安全的。
  • 在单线程程序下,StringBuilder服从更快,因为它不须要加锁,不具备多线程安全而StringBuffer则每次都须要判断锁,服从相对更低
10、final、finally、finalize 难度系数:


  • **final:**修饰符(关键字)有三种用法:修饰类、变量和方法。修饰类时,意味着它不能再派生出新的子类,即不能被继续,因此它和abstract是反义词。修饰变量时,该变量利用中不被改变,必须在声明时给定初值,在引用中只能读取不可修改,即为常量。修饰方法时,也同样只能利用,不能在子类中被重写。
  • **finally:**通常放在try…catch的后面构造最终执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行,可以将开释外部资源的代码写在finally块中。
  • **finalize:**Object类中界说的方法,Java中答应利用finalize() 方法在垃圾网络器将对象从内存中打扫出去之前做须要的清算工作。这个方法是由垃圾网络器在销毁对象时调用的,通过重写finalize() 方法可以整理系统资源或者执行其他清算工作。
11、Object中有哪些方法 难度系数:


  • protected Object clone()—>创建并返回此对象的一个副本。
  • boolean equals(Object obj)—>指示某个其他对象是否与此对象“相等
  • protected void finalize()—>当垃圾采取器确定不存在对该对象的更多引用时,由对象的垃圾采取器调用此方法。
  • Class< extendsObject> getClass()—>返回一个对象的运行时类。
  • int hashCode()—>返回该对象的哈希码值。
  • void notify()—>唤醒在此对象监视器上等待的单个线程。
  • void notifyAll()—>唤醒在此对象监视器上等待的所有线程。
  • String toString()—>返回该对象的字符串表现。
  • void wait()—>导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
    void wait(long timeout)—>导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll()方法,或者高出指定的时间量。
    void wait(long timeout, int nanos)—>导致当前的线程等待,直到其他线程调用此对象的 notify()
12、说一下聚集体系 难度系数:


13、ArrarList和LinkedList区别 难度系数:


  • ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
  • 对于随机访问get和set,ArrayList服从优于LinkedList,因为LinkedList要移动指针。
  • 对于新增和删除操纵add和remove,LinkedList比力占上风,因为ArrayList要移动数据。 这一点要看实际环境的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。
14、HashMap底层是 数组+链表+红黑树,为什么要用这几类结构 难度系数:


  • 数组 Node<K,V>[] table ,哈希表,根据对象的key的hash值进行在数组内里是哪个节点
  • 链表的作用是办理hash冲突,将hash值取模之后的对象存在一个链表放在hash值对应的槽位
  • 红黑树 JDK8利用红黑树来替换高出8个节点的链表,重要是查询性能的提拔,从原来的O(n)到O(logn),
  • 通过hash碰撞,让HashMap不断产生碰撞,那么相同的key的位置的链表就会不断增长,当对这个Hashmap的相应位置进行查询的时间,就会循环遍历这个超级大的链表,性能就会下降,所以改用红黑树
15、HashMap和HashTable区别 难度系数:


  • 线程安全性不同
HashMap是线程不安全的,HashTable是线程安全的,此中的方法是Synchronized,在多线程并发的环境下,可以直接利用HashTable,但是利用HashMap时必须自己增长同步处理。

  • 是否提供contains方法
HashMap只有containsValue和containsKey方法;HashTable有contains、containsKey和containsValue三个方法,此中contains和containsValue方法功能相同。

  • key和value是否答应null值
Hashtable中,key和value都不答应出现null值。HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。

  • 数组初始化和扩容机制
HashTable在不指定容量的环境下的默认容量为11,而HashMap为16,Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。
Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。
16、线程的创建方式 难度系数:


  • 继续Thread类创建线程
  • 实现Runnable接口创建线程
  • 利用Callable和Future创建线程 有返回值
  • 利用线程池创建线程
Java
17、线程的状态转换有什么(生命周期) 难度系数:



  • 新建状态(New) :线程对象被创建后,就进入了新建状态。例如,Thread thread = new Thread()。
  • 就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后,别的线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。
  • 运行状态(Running):线程获取CPU权限进行执行。须要注意的是,线程只能从就绪状态进入到运行状态。
  • 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU利用权,暂时制止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的环境分三种:

    • 等待阻塞-- 通过调用线程的wait()方法,让线程等待某工作的完成。
    • 同步阻塞-- 线程在获取synchronized同步锁失败(因为锁被别的线程所占用),它会进入同步阻塞状态。
    • 其他阻塞-- 通过调用线程的sleep()或join()或发出了I/O哀求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程制止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

  • 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程竣事生命周期。
18、Java中有几种范例的流 难度系数:



19、请写出你最常见的5个RuntimeException 难度系数:


  • java.lang.NullPointerException
空指针异常;出现原因:调用了未经初始化的对象或者是不存在的对象。

  • java.lang.ClassNotFoundException
指定的类找不到;出现原因:类的名称和路径加载错误;通常都是程序试图通过字符串来加载某个类时可能引发异常。

  • java.lang.NumberFormatException
字符串转换为数字异常;出现原因:字符型数据中包罗非数字型字符。

  • java.lang.IndexOutOfBoundsException
数组角标越界异常,常见于操纵数组对象时发生。

  • java.lang.IllegalArgumentException
方法通报参数错误。

  • java.lang.ClassCastException
数据范例转换异常。
20、谈谈你对反射的理解 难度系数:


  • 反射机制
所谓的反射机制就是java语言在运行时拥有一项自观的能力。通过这种能力可以彻底了解自身的环境为下一步的动作做预备。
Java的反射机制的实现要借助于4个类:class,Constructor,Field,Method;此中class代表的时类对 象,Constructor-类的构造器对象,Field-类的属性对象,Method-类的方法对象。通过这四个对象我们可以粗略的看到一个类的各个构成部分。

  • Java反射的作用
在Java运行时环境中,对于恣意一个类,可以知道这个类有哪些属性和方法。对于恣意一个对象,可以调用它的恣意一个方法。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。

  • Java 反射机制提供功能
在运行时判断恣意一个对象所属的类。
在运行时构造恣意一个类的对象。
在运行时判断恣意一个类所具有的成员变量和方法。
在运行时调用恣意一个对象的方法
21、什么是 java 序列化,如何实现 java 序列化 难度系数:


  • 序列化是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操纵,也可将流化后的对象传输于网络之间。序列化是为了办理在对对象流进行读写操纵时所引发的问题。
  • 序 列 化 的 实 现 : 将 需 要 被 序 列 化 的 类 实 现 Serializable 接 口 , 该 接 口 没 有 需 要 实 现 的 方 法 , implements Serializable 只是为了标注该对象是可被序列化的,然后利用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,利用 ObjectOutputStream 对象的 writeObject(Object obj)方法就可以将参数为 obj 的对象写出(即生存其状态),要规复的话则用输入流。
22、Http 常见的状态码 难度系数:


  • 200 OK //客户端哀求乐成
  • 301 Permanently Moved (永世移除),哀求的 URL 已移走。Response 中应该包罗一个 Location URL, 说明资源现在所处的位置
  • 302 Temporarily Moved 临时重定向
  • 400 Bad Request //客户端哀求有语法错误,不能被服务器所理解
  • 401 Unauthorized //哀求未经授权,这个状态代码必须和 WWW-Authenticate 报头域一起利用
  • 403 Forbidden //服务器收到哀求,但是拒绝提供服务
  • 404 Not Found //哀求资源不存在,eg:输入了错误的 URL
  • 500 Internal Server Error //服务器发生不可预期的错误
  • 503 Server Unavailable //服务器当前不能处理客户端的哀求,一段时间后可能规复正常
23、GET 和POST 的区别 难度系数:


  • GET 哀求的数据会附在URL 之后(就是把数据放置在 HTTP 协议头中),以分割URL 和传输数据,参数之间以&相连,如:login.actionname=zhagnsan&password=123456。POST 把提交的数据则放置在是 HTTP 包的包体中。
  • GET 方式提交的数据最多只能是 1024 字节,理论上POST 没有限定,可传较大量的数据。其实这样说是错误的,禁绝确的:“GET 方式提交的数据最多只能是 1024 字节",因为 GET 是通过 URL 提交数据,那么 GET 可提交的数据量就跟URL 的长度有直接关系了。而实际上,URL 不存在参数上限的问题,HTTP 协议规范没有对 URL 长度进行限定。这个限定是特定的浏览器及服务器对它的限定。IE 对URL 长度的限定是2083 字节(2K+35)。对于其他浏览器,如Netscape、FireFox 等,理论上没有长度限定,其限定取决于操纵系统的支持。
  • POST 的安全性要比GET 的安全性高。注意:这里所说的安全性和上面 GET 提到的“安全”不是同个概念。上面“安全”的寄义仅仅是不作数据修改,而这里安全的寄义是真正的 Security 的寄义,比如:通过 GET 提交数据,用户名和暗码将明文出现在 URL 上,因为(1)登录页面有可能被浏览器缓存,(2)其他人查看浏览器的历史记录,那么别人就可以拿到你的账号和暗码了,除此之外,利用 GET 提交数据还可能会造成 Cross-site request forgery 攻击。
  • Get 是向服务器发索取数据的一种哀求,而 Post 是向服务器提交数据的一种哀求,在 FORM(表单)中,Method
  • 默以为"GET",实质上,GET 和 POST 只是发送机制不同,并不是一个取一个发!
24、Cookie 和Session 的区别 难度系数:


  • Cookie 是 web 服务器发送给浏览器的一块信息,浏览器会在当地一个文件中给每个 web 服务器存储 cookie。以后浏览器再给特定的 web 服务器发送哀求时,同时会发送所有为该服务器存储的 cookie
  • Session 是存储在 web 服务器端的一块信息。session 对象存储特定用户会话所需的属性及设置信息。当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中不停存在下去
  • Cookie 和session 的不同点
无论客户端做怎样的设置,session 都能够正常工作。当客户端禁用 cookie 时将无法利用 cookie
在存储的数据量方面:session 能够存储恣意的java 对象,cookie 只能存储 String 范例的对象
第二章-Java高级篇

1、HashMap底层源码 难度系数:

HashMap的底层结构在jdk1.7中由数组+链表实现,在jdk1.8中由数组+链表+红黑树实现,以数组+链表的结构为例。


JDK1.8之前Put方法:

JDK1.8之后Put方法:



HashMap基于哈希表的Map接口实现,是以key-value存储情势存在,即重要用来存放键值对。HashMap 的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的。
JDK1.8 之前 HashMap 由 数组+链表 构成的,数组是 HashMap 的主体,链表则是重要为了办理哈希冲突(两个对象调用的hashCode方法盘算的哈希码值划一导致盘算的数组索引值相同)而存在的(“拉链法”办理冲突).JDK1.8 以后在办理哈希冲突时有了较大的变革,当链表长度大于阈值(或者红黑树的边界值,默以为 8)并且当前数组的长度大于64时,此时此索引位置上的所有数据改为利用红黑树存储。
补充:将链表转换成红黑树前会判断,纵然阈值大于8,但是数组长度小于64,此时并不会将链表变为红黑树。而是选择进行数组扩容。
这样做的目标是因为数组比力小,尽量避开红黑树结构,这种环境下变为红黑树结构,反而会低落服从,因为红黑树须要进行左旋,右旋,变色这些操纵来保持平衡 。同时数组长度小于64时,搜索时间相对要快些。所以综上所述为了提高性能和减少搜索时间,底层在阈值大于8并且数组长度大于64时,链表才转换为红黑树。具体可以参考 treeifyBin方法。
当然固然增了红黑树作为底层数据结构,结构变得复杂了,但是阈值大于8并且数组长度大于64时,链表转换为红黑树时,服从也变的更高效。
注意:可以结合百度hashmap源码解析进行更深入的了解。
史上最详细的 JDK 1.8 HashMap 源码解析_程序员囧辉的博客-CSDN博客
2、JVM内存分哪几个区,每个区的作用是什么 难度系数:



java虚拟机重要分为以下几个区

  • 方法区

    • 有时间也成为永世代,在该区内很少发生垃圾采取,但是并不代表不发生GC,在这里进行的GC重要是对方法区里的常量池和对范例的卸载
    • 方法区重要用来存储已被虚拟机加载的类的信息、常量、静态变量和即时编译器编译后的代码等数据。
    • 该区域是被线程共享的。
    • 方法区里有一个运行时常量池,用于存放静态编译产生的字面量和符号引用。该常量池具有动态性,也就是说常量并不一定是编译时确定,运行时天生的常量也会存在这个常量池中。

  • 虚拟机栈

    • 虚拟机栈也就是我们寻常所称的栈内存,它为java方法服务,每个方法在执行的时间都会创建一个栈帧,用于存储局部变量表、操纵数栈、动态链接和方法出口等信息。
    • 虚拟机栈是线程私有的,它的生命周期与线程相同。
    • 局部变量表里存储的是根本数据范例、returnAddress范例(指向一条字节码指令的地址)和对象引用,这个对象引用有可能是指向对象起始地址的一个指针,也有可能是代表对象的句柄或者与对象相关联的位置。局部变量所需的内存空间在编译器间确定
    • 操纵数栈的作用重要用来存储运算结果以及运算的操纵数,它不同于局部变量表通过索引来访问,而是压栈和出栈的方式
    • 每个栈帧都包罗一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接.动态链接就是将常量池中的符号引用在运行期转化为直接引用。

  • 当地方法栈
当地方法栈和虚拟机栈类似,只不过当地方法栈为Native方法服务。


java堆是所有线程所共享的一块内存,在虚拟机启动时创建,几乎所有的对象实例都在这里创建,因此该区域经常发生垃圾采取操纵。

  • 程序计数器:
内存空间小,字节码解释器工作时通过改变这个计数值可以选取下一条须要执行的字节码指令,分支、循环、跳转、异常处理和线程规复等功能都须要依赖这个计数器完成。该内存区域是唯一一个java虚拟机规范没有规定任何OOM环境的区域。
JEP 122: Remove the Permanent Generation 介绍 静态变量、字符串常量从永世代移动到堆中
3、Java中垃圾网络的方法有哪些 难度系数:

采用分区分代采取头脑:

  • 复制算法 年轻代中利用的是Minor GC,这种GC算法采用的是复制算法(Copying)
a)服从高,缺点:须要内存容量大,比力耗内存
b)利用在占空间比力小、革新次数多的新生区

  • 标志-打扫 老年代一样寻常是由标志打扫或者是标志打扫与标志整理的混合实现
a)服从比力低,会差生碎片。

  • 标志-整理 老年代一样寻常是由标志打扫或者是标志打扫与标志整理的混合实现
a)服从低速度慢,须要移动对象,但不会产生碎片。
4、如何判断一个对象是否存活(或者GC对象的判断方法) 难度系数:


  • 引用计数法
所谓引用计数法就是给每一个对象设置一个引用计数器,每当有一个地方引用这个对象时,就将计数器加一,引用失效时,计数器就减一。当一个对象的引用计数器为零时,说明此对象没有被引用,也就是“死对象”,将会被垃圾采取.
引用计数法有一个缺陷就是无法办理循环引用问题,也就是说当对象A引用对象B,对象B又引用者对象A,那么此时A,B对象的引用计数器都不为零,也就造成无法完成垃圾采取,所以主流的虚拟机都没有采用这种算法。

  • 可达性算法(引用链法)

    • 该算法的根本思路就是通过一些被称为引用链(GC Roots)的对象作为出发点,从这些节点开始向下搜索,搜索走过的路径被称为(Reference Chain),当一个对象到GC Roots没有任何引用链相连时(即从GC Roots节点到该节点不可达),则证明该对象是不可用的。
    • 在java中可以作为GC Roots的对象有以下几种:虚拟机栈中引用的对象、方法区类静态属性引用的对象、方法区常量池引用的对象、当地方法栈JNI引用的对象。

5、什么环境下会产生StackOverflowError(栈溢出)和OutOfMemoryError(堆溢出)怎么排查 难度系数:


  • 引发 StackOverFlowError 的常见原因有以下几种

    • 无限递归循环调用(最常见)
    • 执行了大量方法,导致线程栈空间耗尽
    • 方法内声明了海量的局部变量
    • native 代码有栈上分配的逻辑,并且要求的内存还不小,比如java.net.SocketInputStream.read0会在栈上要求分配一个 64KB 的缓存(64位 Linux)。

  • 引发 OutOfMemoryError的常见原因有以下几种

    • 内存中加载的数据量过于巨大,如一次从数据库取出过多数据
    • 聚集类中有对对象的引用,利用完后未清空,使得JVM不能采取
    • 代码中存在死循环或循环产生过多重复的对象实体
    • 启动参数内存值设定的过小

  • 排查:可以通过jvisualvm进行内存快照分析
参考https://www.cnblogs.com/boboooo/p/13164071.html

  • 栈溢出、堆溢出案例演示

public class StackOverFlowTest {
private static int count = 1;
public static void main(String[] args) {
//模拟栈溢出
//getDieCircle();
//模拟堆溢出
getOutOfMem();
}
public static void getDieCircle(){
System.out.println(count++);
getDieCircle();
}
public static void getOutOfMem(){
while (true) {
Object o = new Object();
System.out.println(o);
}
}
}
Java


6、什么是线程池,线程池有哪些(创建) 难度系数:

线程池就是事先将多个线程对象放到一个容器中,当利用的时间就不用 new 线程而是直接去池中拿线程即可,节流了开辟子线程的时间,提高的代码执行服从
在 JDK 的 java.util.concurrent.Executors 中提供了天生多种线程池的静态方法。
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(4);
ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(4);
ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
然后调用他们的 execute 方法即可。
这4种线程池底层 全部是ThreadPoolExecutor对象的实现,阿里规范手册中规定线程池采用ThreadPoolExecutor自界说的,实际开辟也是。

  • newCachedThreadPool
创建一个可缓存线程池,如果线程池长度高出处理须要,可灵活采取空闲线程,若无可采取,则新建线程。这种范例的线程池特点是:
工作线程的创建数量几乎没有限定(其实也有限定的,数量为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。
如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默以为1分钟),则该工作线程将自动制止。制止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
在利用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统瘫痪。

  • newFixedThreadPool
创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量到达线程池初始的最大数,则将提交的任务存入到池队列中。FixedThreadPool是一个典范且精良的线程池,它具有线程池提高程序服从和节流创建线程时所耗的开销的优点。但是,在线程池空闲时,即线程池中没有可运行任务时,它不会开释工作线程,还会占用一定的系统资源。

  • newSingleThreadExecutor
创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。如果这个线程异常竣事,会有另一个取代它,保证顺序执行。单工作线程最大的特点是可保证顺序地执行各个任务,并且在恣意给定的时间不会有多个线程是运动的。

  • newScheduleThreadPool
创建一个定长的线程池,而且支持定时的以及周期性的任务执行。例如延迟3秒执行。
7、为什么要利用线程池 难度系数:


  • 线程池做的工作重要是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量高出了最 大数量,超出数量的线程列队等候,等别的线程执行完毕,再从队列中取出任务来执行。
  • 重要特点:线程复用;控制最大并发数:管理线程。
第一:低落资源消耗。通过重复利用己创建的线程低落线程创建和销毁造成的消耗。
第二:提高响应速度。当任务到达时,任务可以不须要的等到线程创建就能立即执行。
第三:提高线程的可管理性。线程是稀缺资源,如果无限定的创建,不但会消耗系统资源,还会低落系统的稳定性,利用线程池可以进 行同一的分配,调优和监控
8、线程池底层工作原理 难度系数:



  • 第一步:线程池刚创建的时间,内里没有任何线程,等到有任务过来的时间才会创建线程。当然也可以调用prestartAllCoreThreads()或者prestartCoreThread()方法预创建corePoolSize个线程
  • 第二步:调用execute()提交一个任务时,如果当前的工作线程数<corePoolSize,直接创建新的线程执行这个任务
  • 第三步:如果其时工作线程数量>=corePoolSize,会将任务放入任务队列中缓存
  • 第四步:如果队列已满,并且线程池中工作线程的数量<maximumPoolSize,还是会创建线程执行这个任务
  • 第五步:如果队列已满,并且线程池中的线程已到达maximumPoolSize,这个时间会执行拒绝计谋,JAVA线程池默认的计谋是AbortPolicy,即抛出RejectedExecutionException异常
9、ThreadPoolExecutor对象有哪些参数 怎么设定核心线程数和最大线程数 拒绝计谋有哪些 难度系数:

**参数与作用:**共7个参数

  • **corePoolSize:**核心线程数,
在ThreadPoolExecutor中有一个与它相关的设置:allowCoreThreadTimeOut(默以为false),当allowCoreThreadTimeOut为false时,核心线程会不停存活,哪怕是不停空闲着。而当allowCoreThreadTimeOut为true时核心线程空闲时间高出keepAliveTime时会被采取。

  • **maximumPoolSize:**最大线程数
线程池能容纳的最大线程数,当线程池中的线程到达最大时,此时添加任务将会采用拒绝计谋,默认的拒绝计谋是抛出一个运行时错误(RejectedExecutionException)。值得一提的是,当初始化时用的工作队列为LinkedBlockingDeque时,这个值将无效。

  • **keepAliveTime:**存活时间,
当非核心空闲高出这个时间将被采取,同时空闲核心线程是否采取受allowCoreThreadTimeOut影响。

  • **unit:**keepAliveTime的单元。
  • **workQueue:**任务队列
常用有三种队列,即SynchronousQueue,LinkedBlockingDeque(无界队列),ArrayBlockingQueue(有界队列)。

  • **threadFactory:**线程工厂,
ThreadFactory是一个接口,用来创建worker。通过线程工厂可以对线程的一些属性进行定制。默认直接新建线程。

  • **RejectedExecutionHandler:**拒绝计谋
也是一个接口,只有一个方法,当线程池中的资源已经全部利用,添加新线程被拒绝时,会调用RejectedExecutionHandler的rejectedExecution法。默认是抛出一个运行时异常。
线程池大小设置:

  • 须要分析线程池执行的任务的特性: CPU 密集型还是 IO 密集型
  • 每个任务执行的平均时长大概是多少,这个任务的执行时长可能还跟任务处理逻辑是否涉及到网络传输以及底层系统资源依赖有关系
如果是 CPU 密集型,重要是执行盘算任务,响应时间很快,cpu 不停在运行,这种任务 cpu的利用率很高,那么线程数的设置应该根据 CPU 核心数来决定,CPU 核心数=最大同时执行线程数,加入 CPU 核心数为 4,那么服务器最多能同时执行 4 个线程。过多的线程会导致上下文切换反而使得服从低落。那线程池的最大线程数可以设置为 cpu 核心数+1 如果是 IO 密集型,重要是进行 IO 操纵,执行 IO 操纵的时间较长,这是 cpu 出于空闲状态,导致 cpu 的利用率不高,这种环境下可以增长线程池的大小。这种环境下可以结合线程的等待时长来做判断,等待时间越高,那么线程数也相对越多。一样寻常可以设置 cpu 核心数的 2 倍。
一个公式:线程池设定最佳线程数量 = ((线程池设定的线程等待时间+线程 CPU 时间)/
线程 CPU 时间 )* CPU 数量
这个公式的线程 cpu 时间是预估的程序单个线程在 cpu 上运行的时间(通常利用 loadrunner测试大量运行次数求出平均值)
拒绝计谋:

  • AbortPolicy:直接抛出异常,默认计谋;
  • CallerRunsPolicy:用调用者所在的线程来执行任务;
  • DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务;
  • DiscardPolicy:直接丢弃任务;当然也可以根据应用场景实现 RejectedExecutionHandler 接口,自界说饱和计谋,如纪录日志或持久化存储不能处理的任务
10、常见线程安全的并发容器有哪些 难度系数:


  • CopyOnWriteArrayList、CopyOnWriteArraySet、ConcurrentHashMap
  • CopyOnWriteArrayList、CopyOnWriteArraySet采用写时复制实现线程安全
  • ConcurrentHashMap采用分段锁的方式实现线程安全
11、Atomic原子类了解多少 原理是什么 难度系数:

Java 的原子类都存放在并发包 java.util.concurrent.atomic下,如下图:

根本范例


  • 利用原子的方式更新根本范例
  • AtomicInteger:整型原子类
  • AtomicLong:长整型原子类
  • AtomicBoolean:布尔型原子类
数组范例


  • 利用原子的方式更新数组里的某个元素
  • AtomicIntegerArray:整形数组原子类
  • AtomicLongArray:长整形数组原子类
  • AtomicReferenceArray:引用范例数组原子类
引用范例


  • AtomicReference:引用范例原子类
  • AtomicStampedReference:原子更新引用范例里的字段原子类
  • AtomicMarkableReference :原子更新带有标志位的引用范例
  • AtomicIntegerFieldUpdater:原子更新整形字段的更新器
  • AtomicLongFieldUpdater:原子更新长整形字段的更新器
  • AtomicStampedReference:原子更新带有版本号的引用范例。该类将整数值与引用关联起来,可用于办理原子的更新数据和数据的版本号,以及办理利用 CAS 进行原子更新时可能出现的 ABA 问题

  • AtomicInteger 类利用 CAS (Compare and Swap) + volatile + native 方法来保证原子操纵,从而制止 synchronized 的高开销,执行服从大为提拔。
  • CAS 的原理,是拿期望值和原本的值作比力,如果相同,则更新成新的值。UnSafe 类的 objectFieldOffset() 方法是个当地方法,这个方法是用来拿“原值”的内存地址,返回值是 valueOffset;别的,value 是一个 volatile 变量,因此 JVM 总是可以保证恣意时间的任何线程总能拿到该变量的最新值。
12、synchronized底层实现是什么 lock底层是什么 有什么区别 难度系数:

Synchronized原理:
方法级的同步是隐式,即无需通过字节码指令来控制的,它实现在方法调用和返回操纵之中。JVM可以从方法常量池中的方法表结构(method_info Structure) 中的 ACC_SYNCHRONIZED 访问标志区分一个方法是否同步方法。当方法调用时,调用指令将会 查抄方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先持有monitor(虚拟机规范中用的是管程一词),然后再执行方法,末了再方法完成(无论是正常完成还黑白正常完成)时开释monitor。
代码块的同步是利用monitorenter和monitorexit这两个字节码指令。它们分别位于同步代码块的开始和竣事位置。当jvm执行到monitorenter指令时,当火线程试图获取monitor对象的所有权,如果未加锁或者已经被当火线程所持有,就把锁的计数器+1;当执行monitorexit指令时,锁计数器-1;当锁计数器为0时,该锁就被开释了。如果获取monitor对象失败,该线程则会进入阻塞状态,直到其他线程开释锁。
参考:一篇文章讲透synchronized底层实现原理_忘了带罗盘的船夫的博客-CSDN博客
Lock原理:

  • Lock的存储结构:一个int范例状态值(用于锁的状态变更),一个双向链表(用于存储等待中的线程)
  • Lock获取锁的过程:本质上是通过CAS来获取状态值修改,如果就地没获取到,会将该线程放在线程等待链表中。
  • Lock开释锁的过程:修改状态值,调整等待链表。
  • Lock大量利用CAS+自旋。因此根据CAS特性,lock建议利用在低锁冲突的环境下。
Lock与synchronized的区别:

  • Lock的加锁和解锁都是由java代码配合native方法(调用操纵系统的相关方法)实现的,而synchronize的加锁和解锁的过程是由JVM管理的
  • 当一个线程利用synchronize获取锁时,若锁被其他线程占用着,那么当前只能被阻塞,直到乐成获取锁。而Lock则提供超时锁和可制止等更加灵活的方式,在未能获取锁的 条件下提供一种退出的机制。
  • 一个锁内部可以有多个Condition实例,即有多路条件队列,而synchronize只有一起条件队列;同样Condition也提供灵活的阻塞方式,在未得到关照之前可以通过制止线程以 及设置等待时限等方式退出条件队列。
  • synchronize对线程的同步仅提供独占模式,而Lock即可以提供独占模式,也可以提供共享模式
synchronized
Lock
关键字

自动加锁和开释锁
须要手动调用unlock方法开释锁
jvm层面的锁
API层面的锁
非公平锁
可以选择公平或者非公平锁
锁是一个对象,并且锁的信息生存在了对象中
代码中通过int范例的state标识
有一个锁升级的过程

13、了解ConcurrentHashMap吗 为什么性能比HashTable高,说下原理 难度系数:

ConcurrentHashMap是线程安全的Map容器,JDK8之前,ConcurrentHashMap利用锁分段技能,将数据分成一段段存储,每个数据段设置一把锁,即segment类,这个类继续ReentrantLock来保证线程安全,JKD8的版本取消Segment这个分段锁数据结构,底层也是利用Node数组+链表+红黑树,从而实现对每一段数据就行加锁,也减少了并发冲突的概率。
hashtable类根本上所有的方法都是采用synchronized进行线程安全控制,高并发环境下服从就低落 ,ConcurrentHashMap是采用了分段锁的头脑提高性能,锁粒度更细化
14、ConcurrentHashMap底层原理 难度系数:


  • Java7 中 ConcurrentHashMap 利用的分段锁,也就是每一个 Segment 上同时只有一个线程可以操纵,每一个 Segment 都是一个类似 HashMap 数组的结构,它可以扩容,它的冲突会转化为链表。但是 Segment 的个数一但初始化就不能改变。
Java

  • Java8 中的 ConcurrentHashMap 利用的 Synchronized 锁加 CAS 的机制。结构Node 数组 + 链表 / 红黑树,Node 是类似于一个 HashEntry 的结构。它的冲突再到达一定大小时会转化成红黑树,在冲突小于一定数量时又退回链表。
Java
15、了解volatile关键字不 难度系数:


  • volatile是Java提供的最轻量级的同步机制,保证了共享变量的可见性,被volatile关键字修饰的变量,如果值发生了变革,其他线程立即可见,制止出现脏读现象。
  • volatile禁止了指令重排,可以保证程序执行的有序性,但是由于禁止了指令重排,所以JVM相关的优化没了,服从会偏弱
16、synchronized和volatile有什么区别 难度系数:


  • volatile本质是告诉JVM当前变量在寄存器中的值是不确定的,须要从主存中读取,synchronized则是锁定当前变量,只有当火线程可以访问该变量,其他线程被阻塞住。
  • volatile仅能用在变量级别,而synchronized可以利用在变量、方法、类级别。
  • volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性。
  • volatile不会造成线程阻塞,synchronized可能会造成线程阻塞。
  • volatile标志的变量不会被编译器优化,synchronized标志的变量可以被编译器优化。
17、Java类加载过程 难度系数:


  • 加载 加载时类加载的第一个过程,在这个阶段,将完成一下三件事情:
通过一个类的全限定名获取该类的二进制流。
将该二进制流中的静态存储结构转化为方法去运行时数据结构。
在内存中天生该类的Class对象,作为该类的数据访问入口。

  • 验证 验证的目标是为了确保Class文件的字节流中的信息不回危害到虚拟机.在该阶段重要完成以下四钟验证:
文件格式验证:验证字节流是否符合Class文件的规范,如主次版本号是否在当前虚拟机范围内,常量池中的常量是否有不被支持的范例.
元数据验证:对字节码描述的信息进行语义分析,如这个类是否有父类,是否集成了不被继续的类等。
字节码验证:是整个验证过程中最复杂的一个阶段,通过验证数据流和控制流的分析,确定程序语义是否正确,重要针对方法体的验证。如:方法中的范例转换是否正确,跳转指令是否正确等。
符号引用验证:这个动作在后面的解析过程中发生,重要是为了确保解析动作能正确执行。

  • 预备
预备阶段是为类的静态变量分配内存并将其初始化为默认值,这些内存都将在方法区中进行分配。预备阶段不分配类中的实例变量的内存,实例变量将会在对象实例化时随着对象一起分配在Java堆中。

  • 解析
该阶段重要完成符号引用到直接引用的转换动作。解析动作并不一定在初始化动作完成之前,也有可能在初始化之后。

  • 初始化
初始化时类加载的末了一步,前面的类加载过程,除了在加载阶段用户应用程序可以通过自界说类加载器到场之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中界说的Java程序代码。
18、什么是类加载器,类加载器有哪些 难度系数:

类加载器就是把类文件加载到虚拟机中,也就是说通过一个类的全限定名来获取描述该类的二进制字节流。

  • 重要有以下四种类加载器
启动类加载器(Bootstrap ClassLoader)用来加载java核心类库,无法被java程序直接引用
扩展类加载器(extension class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录内里查找并加载 Java 类
系统类加载器(system class loader)也叫应用类加载器:它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一样寻常来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它
用户自界说类加载器,通过继续 java.lang.ClassLoader类的方式实现

  • 什么时间会利用到加载器?java中的加载器是按需加载,什么时间用到,什么时间加载

    • new对象的时间
    • 访问某个类或者接口的静态变量,或者对该静态变量赋值时
    • 调用类的静态方法时
    • 反射
    • 初始化一个类的子类时,其父类首先会被加载
    • JVM启动时标明的启动类,也就是文件名和类名相同的那个类

19、简述java内存分配与采取计谋以及Minor GC和Major GC(full GC) 难度系数:


  • 内存分配
栈区:栈分为java虚拟机栈和当地方法栈
堆区:堆被所有线程共享区域,在虚拟机启动时创建,唯一目标存放对象实例。堆区是gc的重要区域,通常环境下分为两个区块年轻代和年老代。更细一点年轻代又分为Eden区,重要放新创建对象,From survivor 和 To survivor 生存gc后幸存下的对象,默认环境下各自占比 8:1:1。
方法区:被所有线程共享区域,用于存放已被虚拟机加载的类信息,常量,静态变量等数据。被Java虚拟机描述为堆的一个逻辑部分。习惯是也叫它永世代(permanment generation)
程序计数器:当火线程所执行的行号指示器。通过改变计数器的值来确定下一条指令,比如循环,分支,跳转,异常处理,线程规复等都是依赖计数器来完成。线程私有的。

  • 采取计谋以及Minor GC和Major GC

    • 对象优先在堆的Eden区分配
    • 大对象直接进入老年代
    • 恒久存活的对象将直接进入老年代

当Eden区没有充足的空间进行分配时,虚拟机会执行一次Minor GC.Minor GC通常发生在新生代的Eden区,在这个区的对象生存期短,往往发生GC的频率较高,采取速度比力快;Full Gc/Major GC 发生在老年代,一样寻常环境下,触发老年代GC的时间不会触发Minor GC,但是通过设置,可以在Full GC之进步行一次Minor GC这样可以加速老年代的采取速度。
20、如何查看java死锁 难度系数:

Java
死锁代码演示

  • 程序运行,历程没有制止。


  • 通过jps查看java历程,找到没有制止的历程


  • 通过jstack 9060 查看历程具体执行信息

21、Java死锁如何制止 难度系数:

造成死锁的几个原因
1.一个资源每次只能被一个线程利用
2.一个线程在阻塞等待某个资源时,不开释已占据资源
3.一个线程已经得到的资源,在未利用完之前,不能被强行剥夺
4.若干线程形成头尾相接的循环等待资源关系
这是造成死锁必须要到达的4个条件,如果要制止死锁,只须要不满足此中某一个条件即可。而此中前3个条件是作为锁要符合的条件,所以要制止死锁就须要打破第4个条件,不出现循环等待锁的关系。
在开辟过程中
1.要注意加锁顺序,保证每个线程按同样的顺序进行加锁
2.要注意加锁时限,可以针对锁设置一个超时时间
3.要注意死锁查抄,这是一种防备机制,确保在第一时间发现死锁并进行办理
第三章-java框架篇

1、简朴的谈一下SpringMVC的工作流程 难度系数:



  • 用户发送哀求至前端控制器DispatcherServlet
  • DispatcherServlet收到哀求调用HandlerMapping处理器映射器。
  • 处理器映射器找到具体的处理器,天生处理器对象及处理器拦截器(如果有则天生)一并返回给DispatcherServlet。
  • DispatcherServlet调用HandlerAdapter处理器适配器
  • HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
  • Controller执行完成返回ModelAndView
  • HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
  • DispatcherServlet将ModelAndView传给ViewReslover视图解析器
  • ViewReslover解析后返回具体View
  • DispatcherServlet根据View进行渲染视图(即将模型数据添补至视图中)。
  • DispatcherServlet响应用户
2、说出Spring或者SpringMVC中常用的5个注解 难度系数:


  • @Component 根本注解,标识一个受Spring管理的组件
  • @Controller 标识为一个表现层的组件
  • @Service 标识为一个业务层的组件
  • @Repository 标识为一个持久层的组件
  • @Autowired 自动装配
  • @Qualifier(“”) 具体指定要装配的组件的id值
  • @RequestMapping() 完成哀求映射
  • @PathVariable 映射哀求URL中占位符到哀求处理方法的形参
只要说出几个注解并解释寄义即可,如上答案只做参考
3、简述SpringMVC中如何返回JSON数据 难度系数:

Step1:在项目中加入json转换的依赖,例如jackson,fastjson,gson等
Step2:在哀求处理方法中将返回值改为具体返回的数据的范例, 例如数据的聚集类List等
Step3:在哀求处理方法上利用@ResponseBody注解
4、谈谈你对Spring的理解 难度系数:

Spring 是一个开源框架,为简化企业级应用开辟而生。Spring 可以是使简朴的JavaBean 实现从前只有EJB 才能实现的功能。Spring 是一个 IOC 和 AOP 容器框架。
Spring 容器的重要核心是:
控制反转(IOC),传统的 java 开辟模式中,当须要一个对象时,我们会自己利用 new 或者 getInstance 等直接或者间接调用构造方法创建一个对象。而在 spring 开辟模式中,spring 容器利用了工厂模式为我们创建了所须要的对象,不须要我们自己创建了,直接调用spring 提供的对象就可以了,这是控制反转的头脑。
依赖注入(DI),spring 利用 javaBean 对象的 set 方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所须要的值的过程,就是依赖注入的头脑。
面向切面编程(AOP),在面向对象编程(oop)头脑中,我们将事物纵向抽成一个个的对象。而在面向切面编程中,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如权限控制、事物管理,纪录日志等公用操纵处理的过程就是面向切面编程的头脑。AOP 底层是动态署理,如果是接口采用 JDK 动态署理,如果是类采用CGLIB 方式实现动态署理。
5、Spring中常用的设计模式 难度系数:


  • 署理模式——spring 中两种署理方式,若目标对象实现了若干接口,spring 利用jdk 的java.lang.reflect.Proxy类署理。若目标兑现没有实现任何接口,spring 利用 CGLIB 库天生目标类的子类。
  • 单例模式——在 spring 的设置文件中设置 bean 默以为单例模式。
  • 模板方式模式——用来办理代码重复的问题。
比如:RestTemplate、JmsTemplate、JpaTemplate

  • 工厂模式——在工厂模式中,我们在创建对象时不会对客户端袒露创建逻辑,并且是通过利用同一个接口来指向新创建的对象。Spring 中利用 beanFactory 来创建对象的实例。
6、Spring循环依赖问题 难度系数:

常见问法

请解释一下spring中的三级缓存
三级缓存分别是什么三个Map有什么异同
什么是循环依赖请你谈谈看过spring源码吗
如何检测是否存在循环依赖实际开辟中见过循环依赖的异常吗
多例的环境下,循环依赖问题为什么无法办理
什么是循环依赖


两种注入方式对循环依赖的影响

官方解释
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-dependency-resolution
相关概念

实例化:堆内存中申请空间

初始化:对象属性赋值


三级缓存

名称
对象名
寄义
一级缓存
singletonObjects
存放已经经历了完整生命周期的Bean对象
二级缓存
earlySingletonObjects
存放早期袒露出来的Bean对象,Bean的生命周期未竣事(属性还未添补完)
三级缓存
singletonFactories
存放可以天生Bean的工厂
四个关键方法


package org.springframework.beans.factory.support;
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/**
单例对象的缓存:bean名称—bean实例,即:所谓的单例池。
表现已经经历了完整生命周期的Bean对象
第一级缓存
*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/**
早期的单例对象的高速缓存: bean名称—bean实例。
表现 Bean的生命周期还没走完(Bean的属性还未添补)就把这个 Bean存入该缓存中也就是实例化但未初始化的 bean放入该缓存里
第二级缓存
*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/**
单例工厂的高速缓存:bean名称—ObjectFactory
表现存放天生 bean的工厂
第三级缓存
*/
private final Map<String, ObjectFactory<>> singletonFactories = new HashMap<>(16);
}
debug源代码过程

须要22个断点(可选)
1,A创建过程中须要B,于是A将自己放到三级缓内里,去实例化B
2,B实例化的时间发现须要A,于是B先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了A然后把三级缓存内里的这个A放到二级缓存内里,并删除三级缓存内里的A
3,B顺遂初始化完毕,将自己放到一级缓存内里(此时B内里的A依然是创建中状态)
然后返来接着创建A,此时B已经创建竣事,直接从一级缓存内里拿到B,然后完成创建,并将A自己放到一级缓存内里。
总结

1,Spring创建 bean重要分为两个步调,创建原始bean对象,接着去添补对象属性和初始化。
2,每次创建 bean之前,我们都会从缓存中查下有没有该bean,因为是单例,只能有一个。
3,当创建 A的原始对象后,并把它放到三级缓存中,接下来就该添补对象属性了,这时间发现依赖了B,接着就又去创建B,同样的流程,创建完B添补属性时又发现它依赖了A又是同样的流程,不同的是:这时间可以在三级缓存中查到刚放进去的原始对象A。
所以不须要继续创建,用它注入 B,完成 B的创建既然 B创建好了,所以 A就可以完成添补属性的步调了,接着执行剩下的逻辑,闭环完成
Spring办理循环依赖依赖的是Bean的"中心态"这个概念,而这个中心态指的是已经实例化但还没初始化的状态—>半制品。实例化的过程又是通过构造器创建的,如果A还没创建好出来怎么可能提前曝光,所以构造器的循环依赖无法办理
其他衍生问题

问题1:为什么构造器注入属性无法办理循环依赖问题
由于spring中的bean的创建过程为先实例化 再初始化(在进行对象实例化的过程中不必赋值)将实例化好的对象袒露出去,供其他对象调用,然而利用构造器注入,必须要利用构造器完成对象的初始化的操纵,就会陷入死循环的状态
问题2:一级缓存能不能办理循环依赖问题 不能
在三个级别的缓存中存储的对象是有区别的 一级缓存为完全实例化且初始化的对象 二级缓存实例化但未初始化对象 如果只有一级缓存,如果是并发操纵下,就有可能取到实例化但未初始化的对象,就会出现问题
问题3:二级缓存能不能办理循环依赖问题
理论上二级缓存可以办理循环依赖问题,但是须要注意,为什么须要在三级缓存中存储匿名内部类(ObjectFactory),原因在于 须要创建署理对象 eg:现有A类,须要天生署理对象 A是否须要进行实例化(须要) 在三级缓存中存放的是天生具体对象的一个匿名内部类,该类可能是署理类也可能是普通的对象,而利用三级缓存可以保证无论是否须要是署理对象,都可以保证利用的是同一个对象,而不会出现,一会儿利用普通bean 一会儿利用署理类
7、介绍一下Spring bean 的生命周期、注入方式和作用域 难度系数:

Bean的生命周期
(1)默认环境下,IOC容器中bean的生命周期分为五个阶段:


  • 调用构造器 或者是通过工厂的方式创建Bean对象
  • 给bean对象的属性注入值
  • 调用初始化方法,进行初始化, 初始化方法是通过init-method来指定的.
  • 利用
  • IOC容器关闭时, 销毁Bean对象.
(2)当加入了Bean的后置处理器后,IOC容器中bean的生命周期分为七个阶段:


  • 调用构造器 或者是通过工厂的方式创建Bean对象
  • 给bean对象的属性注入值
  • 执行Bean后置处理器中的 postProcessBeforeInitialization
  • 调用初始化方法,进行初始化, 初始化方法是通过init-method来指定的.x
  • 执行Bean的后置处理器中 postProcessAfterInitialization
  • 利用
  • IOC容器关闭时, 销毁Bean对象
只须要回答出第一点即可,第二点也回答可适当 加分。
注入方式:
通过 setter 方法注入
通过构造方法注入
Bean的作用域
统共有四种作用域:


  • Singleton 单例的
  • Prototype 原型的
  • Request
  • Session
8、请描述一下Spring 的事务管理 难度系数:

(1)声明式事务管理的界说:用在 Spring 设置文件中声明式的处理事务来代替换码式的处理事务。这样的好处是,事务管理不侵入开辟的组件,具体来说,业务逻辑对象就不会心识到正在事务管理之中,事实上也应该云云,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策划的话,也只须要在界说文件中重新设置即可,这样维护起来极其方便。
基于 TransactionInterceptor 的声明式事务管理:两个次要的属性: transactionManager,用来指定一个事务治理器, 并将具体事务相关的操纵拜托给它; 其他一个是 Properties 范例的transactionAttributes 属性,该属性的每一个键值对中,键指定的是方法名,方法名可以利用通配符, 而值就是表现呼应方法的所运用的事务属性。
(2)基于 @Transactional 的声明式事务管理:Spring 2.x 还引入了基于 Annotation 的体式格式,具体次要触及@Transactional 标注。@Transactional 可以浸染于接口、接口方法、类和类方法上。算作用于类上时,该类的统统public 方法将都具有该范例的事务属性。
(3)编程式事物管理的界说:在代码中显式挪用 beginTransaction()、commit()、rollback()等事务治理相关的方法, 这就是编程式事务管理。Spring 对事物的编程式管理有基于底层 API 的编程式管理和基于 TransactionTemplate 的编程式事务管理两种方式。
9、MyBatis中 #{}和${}的区别是什么 难度系数:

#{}是预编译处理,${}是字符串更换;
Mybatis在处理#{}时,会将sql中的#{}更换为号,调用PreparedStatement的set方法来赋值;
Mybatis在处理                                           时,就是把                              {}时,就是把                  时,就是把{}更换成变量的值;
利用#{}可以有效的防止SQL注入,提高系统安全性。
10、Mybatis 中一级缓存与二级缓存 难度系数:


  • MyBatis的缓存分为一级缓存和 二级缓存。
一级缓存是SqlSession级别的缓存,默认开启。
二级缓存是NameSpace级别(Mapper)的缓存,多个SqlSession可以共享,利用时须要进行设置开启。

  • 缓存的查找顺序:二级缓存 => 一级缓存 => 数据库
11、MyBatis如何获取自动天生的(主)键值 难度系数:

在标签中利用 useGeneratedKeys和keyProperty 两个属性来获取自动天生的主键值。
示例:
insert into names (name) values (#{ name}) Java
12、简述Mybatis的动态SQL,列出常用的6个标签及作用 难度系数:

动态SQL是MyBatis的强大特性之一 基于功能强大的OGNL表达式。
动态SQL重要是来办理查询条件不确定的环境,在程序运行期间,根据提交的条件动态的完成查询
常用的标签:
  : 进行条件的判断
:在判断后的SQL语句前面添加WHERE关键字,并处理SQL语句开始位置的AND 或者OR的问题
:可以在SQL语句前后进行添加指定字符 或者去掉指定字符.
: 重要用于修改操纵时出现的逗号问题
  :类似于java中的switch语句.在所有的条件中选择其一
:迭代操纵
13、Mybatis 如何完成MySQL的批量操纵 难度系数:

MyBatis完成MySQL的批量操纵重要是通过标签来拼装相应的SQL语句
例如:
<insert** id=“insertBatch” >
insert into tbl_employee(last_name,email,gender,d_id) values
<foreach** collection=“emps” item=“curr_emp” separator=“,”**>
(#{ curr_emp.lastName},#{ curr_emp.email},#{ curr_emp.gender},#{ curr_emp.dept.id})


Java
14、谈谈怎么理解SpringBoot框架 难度系数:

Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式办理方案,重要是简化了利用 Spring 的难度,简省了繁重的设置,提供了各种启动器,开辟者能快速上手。

Spring Boot的优点


  • 独立运行
Spring Boot而且内嵌了各种servlet容器,Tomcat、Jetty等,现在不再须要打成war包摆设到容器中,Spring Boot只要打成一个可执行的jar包就能独立运行,所有的依赖包都在一个jar包内。


  • 简化设置
spring-boot-starter-web启动器自动依赖其他组件,简少了maven的设置。除此之外,还提供了各种启动器,开辟者能快速上手。


  • 自动设置
Spring Boot能根据当前类路径下的类、jar包来自动设置bean,如添加一个spring-boot-starter-web启动器就能拥有web的功能,无需其他设置。


  • 无代码天生和XML设置
Spring Boot设置过程中无代码天生,也无需XML设置文件就能完成所有设置工作,这统统都是借助于条件注解完成的,这也是Spring4.x的核心功能之一。


  • 应用监控
Spring Boot提供一系列端点可以监控服务及应用,做康健检测。
Spring Boot缺点:
Spring Boot固然上手很容易,但如果你不了解其核心技能及流程,所以一旦遇到问题就很棘手,而且现在的办理方案也不是很多,须要一个完满的过程。
15、Spring Boot 的核心注解是哪个 它重要由哪几个注解构成的 难度系数:

启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,重要组合包罗了以下 3 个注解:


  • @SpringBootConfiguration:组合了 @Configuration 注解,实现设置文件的功能。
  • @EnableAutoConfiguration:打开自动设置的功能,也可以关闭某个自动设置的选项,

    • 如关闭数据源自动设置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。

  • @ComponentScan:Spring组件扫描。
16、Spring Boot自动设置原理是什么 难度系数:

注解 @EnableAutoConfiguration, @Configuration, @ConditionalOnClass 就是自动设置的核心,
首先它得是一个设置文件,其次根据类路径下是否有这个类去自动设置。
@EnableAutoConfiguration是实现自动设置的注解
@Configuration表现这是一个设置文件
具体参考文档:
Spring Boot自动设置原理、实战
17、SpringBoot设置文件有哪些 怎么实现多环境设置 难度系数:

Spring Boot 的核心设置文件是 application 和 bootstrap 设置文件。
application 设置文件这个容易理解,重要用于 Spring Boot 项目标自动化设置。
bootstrap设置文件的特性:


  • bootstrap 由父 ApplicationContext 加载,比 applicaton 优先加载
  • bootstrap 内里的属性不能被覆盖
bootstrap 设置文件有以下几个应用场景:


  • 利用 Spring Cloud Config 设置中心时,这时须要在 bootstrap 设置文件中添加连接到设置中心的设置属性来加载外部设置中心的设置信息;
  • 一些固定的不能被覆盖的属性;
  • 一些加密/解密的场景;
提供多套设置文件,如:
applcation.properties
application-dev.properties
application-test.properties
application-prod.properties
运行时指定具体的设置文件,具体请看这篇文章《Spring Boot Profile 不同环境设置》。
18、SpringBoot和SpringCloud是什么关系 难度系数:

Spring Boot 是 Spring 的一套快速设置脚手架,可以基于Spring Boot 快速开辟单个微服务,Spring Cloud是一个基于Spring Boot实现的开辟工具;Spring Boot专注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架; Spring Boot利用了默认大于设置的理念,很多集成方案已经帮你选择好了,能不设置就不设置,Spring Cloud很大的一部分是基于Spring Boot来实现,必须基于Spring Boot开辟。
可以单独利用Spring Boot开辟项目,但是Spring Cloud离不开 Spring Boot。
19、SpringCloud都用过哪些组件 介绍一下作用 难度系数:


  • Nacos–作为注册中心和设置中心,实现服务注册发现和服务康健监测及设置信息同一管理
  • Gateway–作为网关,作为分布式系统同一的收支口,进行服务路由,同一鉴权等
  • OpenFeign–作为长途调用的客户端,实现服务之间的长途调用
  • Sentinel–实现系统的熔断限流
  • Sleuth–实现服务的链路追踪
20、Nacos作用以及注册中心的原理 难度系数:

Nacos英文全称Dynamic Naming and Configuration Service,Na为naming/nameServer即注册中心,co为configuration即注册中心,service是指该注册/设置中心都是以服务为核心。
Nacos注册中心分为server与client,server采用Java编写,为client提供注册发现服务与设置服务。而client可以用多语言实现,client与微服务嵌套在一起,nacos提供sdk和openApi,如果没有sdk也可以根据openApi手动写服务注册与发现和设置拉取的逻辑。

服务注册原理
服务注册方法:以Java nacos client v1.0.1 为例子,服务注册的计谋的是每5秒向nacos server发送一次心跳,心跳带上了服务名,服务ip,服务端口等信息。同时 nacos server也会向client 主动发起康健查抄,支持tcp/http查抄。如果15秒内无心跳且康健查抄失败则以为实例不康健,如果30秒内康健查抄失败则剔除实例。

21、Feign工作原理 难度系数:

主程序入口添加了@EnableFeignClients注解开启对FeignClient扫描加载处理。根据Feign Client的开辟规范,界说接口并加@FeignClient注解。当程序启动时,会进行包扫描,扫描所有@FeignClient的注解的类,并且讲这些信息注入Spring IOC容器中,当界说的的Feign接口中的方法被调用时,通过JDK的署理方式,来天生具体的RequestTemplate.当天生署理时,Feign会为每个接口方法创建一个RequestTemplate。当天生署理时,Feign会为每个接口方法创建一个RequestTemplate对象,该对象封装HTTP哀求须要的全部信息,如哀求参数名,哀求方法等信息都是在这个过程中确定的。然后RequestTemplate天生Request,然后把Request交给Client行止理,这里指的时Client可以时JDK原生的URLConnection,Apache的HttpClient,也可以时OKhttp,末了Client被封装到LoadBalanceClient类,这个类结合Ribbon负载均衡发器服务之间的调用。

第四章-MySQL

1、Select 语句完整的执行顺序 难度系数:

SQL Select 语句完整的执行顺序:
(1)from 子句组装来自不同数据源的数据;
(2)where 子句基于指定的条件对纪录行进行筛选;
(3)group by 子句将数据分别为多个分组;
(4)利用聚集函数进行盘算;
(5)利用 having 子句筛选分组;
(6)盘算所有的表达式;
(7)select 的字段;
(8)利用order by 对结果集进行排序。
2、MySQL事务 难度系数:

事务的根本要素(ACID)


  • 原子性(Atomicity):事务开始后所有操纵,要么全部做完,要么全部不做,不可能停滞在中心环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操纵就像没有发生一样。也就是说事务是一个不可分割的团体,就像化学中学过的原子,是物质构成的根本单元
  • 划一性(Consistency):事务开始前和竣事后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。
  • 隔离性(Isolation):同一时间,只答应一个事务哀求同一数据,不同的事务之间相互没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程竣事前,B不能向这张卡转账。
  • 持久性(Durability):事务完成后,事务对数据库的所有更新将被生存到数据库,不能回滚。
MySQL事务隔离级别:
事务隔离级别
脏读
不可重复读
幻读
读未提交(read-uncommitted)



读提交(read-committed)



可重复读(repeatable-read)



串行化(serializable)



事务的并发问题


  • 脏读:事务A读取了事务B更新的数据,然后B回滚操纵,那么A读取到的数据是脏数据
  • 不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不划一
  • 幻读:系统管理员A将数据库中所有弟子的结果从具体分数改为ABCDE等级,但是系统管理员B就在这个时间插入了一条具体分数的纪录,当系统管理员A改竣事后发现还有一条纪录没有改过来,就好像发生了幻觉一样,这就叫幻读。
如何办理脏读、幻读、不可重复读


  • 脏读: 隔离级别为 读提交、可重复读、串行化可以办理脏读
  • 不可重复读:隔离级别为可重复读、串行化可以办理不可重复读
  • 幻读:隔离级别为串行化可以办理幻读、通过MVCC + 区间锁可以办理幻读
小结:
不可重复读的和幻读很容易肴杂,不可重复读偏重于修改,幻读偏重于新增或删除。办理不可重复读的问题只需锁住满足条件的行,办理幻读须要锁表
3、MyISAM和InnoDB的区别 难度系数:

MyISAM
InnoDB
事务
不支持
支持

表锁
表锁、行锁
文件存储
3个
1个
外键
不支持
支持
4、灰心锁和乐观锁的怎么实现 难度系数:

**灰心锁:**select…for update是MySQL提供的实现灰心锁的方式。
例如:select price from item where id=100 for update
此时在items表中,id为100的那条数据就被我们锁定了,别的的要执行select price from items where id=100 for update的事务必须等本次事务提交之后才能执行。这样我们可以保证当前的数据不会被别的事务修改。MySQL有个问题是select…for update语句执行中所有扫描过的行都会被锁上,因此在MySQL中用灰心锁务必须确定走了索引,而不是全表扫描,否则将会将整个数据表锁住。
**乐观锁:**乐观锁相对灰心锁而言,它以为数据一样寻常环境下不会造成冲突,所以在数据进行提交更新的时间,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回错误信息,让用户决定如何去做。
利用数据版本号(version)机制是乐观锁最常用的一种实现方式。一样寻常通过为数据库表增长一个数字范例的 “version” 字段,当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值+1。当我们提交更新的时间,判断数据库表对应纪录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则以为是逾期数据,返回更新失败。
举例:
//1: 查询出商品信息
select (quantity,version) from items where id=100;
//2: 根据商品信息天生订单
insert into orders(id,item_id) values(null,100);
//3: 修改商品的库存
update items set quantity=quantity-1,version=version+1 where id=100 and version=#{version};
5、聚簇索引与非聚簇索引区别 难度系数:

都是B+树的数据结构
聚簇索引:将数据存储与索引放到了一块、并且是按照一定的顺序组织的,找到索引也就找到了数据,数据的物理存放顺序与索引顺序是划一的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的
非聚簇索引叶子节点不存储数据、存储的是数据行地址,也就是说根据索引查找到数据行的位置再取磁盘查找数据,这个就有点类似一本书的目录,比如我们要找第三章第一节,那我们先在这个目录内里找,找到对应的页码后再去对应的页码看文章。
上风:
1、查询通过聚簇索引可以直接获取数据,相比非聚簇索引须要第二次查询(非覆盖索引的环境下)服从要高
2、聚簇索引对于范围查询的服从很高,因为其数据是按照大小分列的
3、聚簇索引适合用在排序的场合,非聚簇索引不适合
劣势;
1、维护索引很昂贵,特别是插入新行或者主键被更新导至要分页(pagesplit)的时间。建议在大量插入新行后,选在负载较低的时间段,通过OPTIMIZETABLE优化表,因为必须被移动的行数据可能造成碎片。利用独享表空间可以弱化碎片
2、表因为利用uuId(随机ID)作为主键,使数据存储希罕,这就会出现聚簇索引有可能有比全表扫面更慢,所以建议利用int的auto_increment作为主键
3、如果主键比力大的话,那辅助索引将会变的更大,因为辅助索引的叶子存储的是主键值,过长的主键值,会导致非叶子节点占用占用更多的物理空间
6、什么环境下mysql会索引失效 难度系数:

失效条件:


  • where 后面利用函数
  • 利用or条件
  • 含糊查询 %放在前边
  • 范例转换
  • 组合索引 (最佳左前缀匹配原则)
#查询条件用到了盘算或者函数
explain SELECT * from test_slow_query where age = 20
explain SELECT * from test_slow_query where age +10 = 30
#含糊查询
EXPLAIN SELECT * from test_slow_query where NAME like ‘%吕布’
EXPLAIN SELECT * from test_slow_query where NAME like ‘%吕布%’
EXPLAIN SELECT * from test_slow_query where NAME like ‘吕布&’
#用到了or条件
EXPLAIN SELECT * from test_slow_query where NAME = ‘吕布’ or name = “aaa”
#范例不匹配查询
explain SELECT * from test_slow_query where NAME = 11
explain SELECT * from test_slow_query where NAME = ‘11’
SQL
7、B+tree 与 B-tree区别 难度系数:

原理:分批次的将磁盘块加载进内存中进行检索,若查到数据,则直接返回,若查不到,则开释内存,并重新加载划一数据量的索引进内存,重新遍历
结构:数据 向下的指针 指向数据的指针
特点:
1,节点排序
2 .一个节点了可以存多个元索,多个元索也排序了

结构:数据向下的指针
特点:
1.拥有B树的特点
2.叶子节点之间有指针
3.非叶子节点上的元素在叶子节点上都冗余了,也就是叶子节点中存储了所有的元素,并且排好顺序

从结构上看,B+Tree相较于B-Tree而言 缺少了指向数据的指针也就红色小方块;
Mysq|索引利用的是B+树,因为索引是用来加速查询的,而B+树通过对数据进行排序所以是可以提高查询速度的,然后通过一个节点中可以存储多个元素,从而可以使得B+树的高度不会太高,在Mysql中一个Innodb页就是一个B+树节点,一个Innodb页默认16kb,所以一样寻常环境下一颗两层的B+树可以存2000万行左右的数据,然后通过利用B+树叶子节点存储了所有数据并且进行了排序,并且叶子节点之间有指针,可以很好的支持全表扫描,范围查找等SQL语句
文章保举:B-Tree和B+Tree的区别 - 简书
8、以MySQL为例Linux下如何排查问题 难度系数:

类似提问方式:如果线上环境出现问题比如网站卡顿重则瘫痪 如何是好
—>linux—>mysql/redis/nacos/sentinel/sluth—>可以从以上提到的技能点中选择一个自己熟悉单技能点进行分析
以mysql为例
1,架构层面 是否利用主从
2,表结构层面 是否满足通例的表设计规范(大量冗余字段会导致查询会变得很复杂)
3,sql语句层面()
前提:由于慢查询日志纪录默认是关闭的,所以开启数据库mysql的慢查询纪录 的功能 从慢查询日志中去获取哪些sql语句时慢查询 默认10S ,从中获取到sql语句进行分析
3.1 explain 分析一条sql

Id:执行顺序 如果单表的话,无参考价值 如果是关联查询,会据此判断主表 从表
Select_type:simple
Table:表
Type:ALL 未创建索引 、const、 常量ref其他索引 、eq_ref 主键索引、
Possible_keys
Key实际是到到索引到字段
Key_len索引字段数据结构所利用长度与是否有默认值null 以及对应字段到数据范例有关,有一个理论值 有一个实际利用值也即key_len的值
Rows检索的行数与查询返回的行数无关
Extra常见的值:usingfilesort 利用磁盘排序算法进行排序,事关排序 分组 的字段是否利用索引的核心参考值
还可能这样去提问:sql语句中哪些位置适合建索引/索引建立在哪个位置
Select id,name,agefrom user where id=1 and name=”xxx”order by age
总结: 查询字段 查询条件(最常用) 排序/分组字段
补充:如何判断是数据库的问题可以借助于top命令


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

怀念夏天

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表