网站前台设计软件,广州网站推广制作,可以做微商的网站,wordpress的点商最新版本Java八股文复习#xff0c;每天更新一篇#xff0c;博主正在持续努力更新中~~~ 一、Java基础篇1、怎么理解面向对象#xff1f;简单说说封装、继承、多态三大特性#xff1f;2、多态体现在哪几个方面#xff1f;3、面向对象的设计原则你知道有哪些吗#xff1f;4… 最新版本Java八股文复习每天更新一篇博主正在持续努力更新中~~~ 一、Java基础篇1、怎么理解面向对象简单说说封装、继承、多态三大特性2、多态体现在哪几个方面3、面向对象的设计原则你知道有哪些吗4、重载与重写有什么区别?5、深拷贝和浅拷贝的区别6、实现深拷贝的三种方法是什么7、 什么是泛型8、java创建对象有哪些方式9、什么是反射10、有什么异常分为什么类型11、 与 equals 有什么区别12、StringBuffer和StringBuild区别是什么13、completableFuture是什么的14、怎么把一个对象从一个jvm转移到另一个jvm?二、Java集合篇1、说说Java中的集合2、Java中的线程安全的集合是什么3、Collections和Collection的区别4、为什么ArrayList不是线程安全的具体来说是哪里不安全5、ArrayList的扩容机制说一下6、线程安全的 List CopyonWriteArraylist是如何实现线程安全的7、HashMap的底层原理介绍一下8、了解的哈希冲突解决方法有哪些9、hashmap的put过程介绍一下10、ConcurrentHashMap怎么实现的11、ConcurrentHashMap用了悲观锁还是乐观锁?12、HashTable 底层实现原理是什么13、Set集合有什么特点如何实现key无重复的14、有序的Set是什么记录插入顺序的集合是什么 三、Java并发篇1、Java的线程安全在三个方面的体现2、保证数据的一致性有哪些方案呢3、线程的创建方式有哪些?4、Java线程的状态有哪些5、wait 状态下的线程如何进行恢复到 running 状态?6、如何保证多线程安全7、Java中有哪些常用的锁8、synchronized和reentrantlock的工作原理9、详细介绍一下Java中的waitjoinsleep方法10、synchronized和Reentrantlock区别11、如何理解可重入锁12、ReentrantLock和synchronized 如何实现可重入锁的13、syncronized锁升级的过程讲一下14、什么是AQS和CAS15、Threadlocal作用原理具体里面存的key value是啥会有什么问题如何解决?16、悲观锁和乐观锁的区别17、Java中想实现一个乐观锁都有哪些方式18、CAS 有什么缺点19、voliatle关键字有什么作用20、什么是公平锁和非公平锁21、介绍一下线程池的工作原理22、线程池的参数有哪些23、线程池工作队列满了有哪些拒接策略24、线程池种类有哪些 四、SpringSpringBootSpringCloud篇1、Spring框架的核心特性有什么2、Spring IOC、Spring IOC容器分别是什么二者有何区别3、Spring AOP介绍一下4、IOC和AOP是通过什么机制来实现的?5、静态代理和动态代理的区别是什么6、spring是如何解决循环依赖的以及循环产生的原因是什么7、Spring三级缓存是什么过程是怎么样的8、Spring三级缓存的数据结构是什么9、Spring框架中都用到了哪些设计模式10、Spring、Spring MVC、Spring Boot常用的注解11、Spring生命周期中的实例化和初始化阶段有何区别12、Spring 中Bean的生命周期说一下13、Spring bean的作用域有哪些14、MVC分层介绍一下15、为什么使用springboot比Spring好在哪里16、SpringBoot自动装配原理是什么17、Mybatis里的 #{} 和 ${} 的区别18、负载均衡有哪些算法 五、MySQL篇1、数据库三大范式是什么2、MySQL 怎么连表查询3、MySQL如何避免重复插入数据4、CHAR 和 VARCHAR有什么区别5、mysql中的一些基本函数你知道哪些6、SQL查询语句的执行顺序是如何的7、MySQL引擎有哪些你有什么了解8、MySQL的InnoDB与MyISAM的区别9、索引的分类是什么10、MySQL聚簇索引和非聚簇索引的区别是什么11、索引失效有哪些12、什么情况回进行回表查询13、什么是覆盖索引14、如何进行索引优化15、事务的特性是什么详细说说16、MySQL中什么是脏读不可重复读幻读17、对于并发问题mysql有什么方法解决18、事务的隔离级别有哪些19、MySQL默认的隔离级别是什么?20、MVCC是什么21、MysSQL中有哪些锁22、日志文件是分成了哪几种23、MySQL中explain有什么作用并详细说说它的参数24、MySQL主从复制了解吗具体复制过程是什么? 一、Java基础篇
1、怎么理解面向对象简单说说封装、继承、多态三大特性
面向对象是一种编程范式它将现实世界中的事物抽象为对象对象具有属性(称为字段或属性)和行为(称为方法)。面向对象编程的设计思想是以对象为中心通过对象之间的交互来完成程序的功能具有灵活性和可扩展性通过封装和继承可以更好地应对需求变化。
Java面向对象的三大特性包括:继承、封装、多态
封装: 封装是指将对象的属性(数据)和行为(方法)结合在一起对外隐藏对象的内部细节仅通过对象提供的接口与外界交互。封装的目的是增强安全性和简化编程使得对象更加独继承: 继承是指一个类子类可以继承另一个类父类的属性和方法。继承使得代码能够复用减少重复代码同时也支持创建层次结构。多态: 指同一个接口或基类可以表示多个不同类型的接口或者对象。
2、多态体现在哪几个方面
方法重载方法重写接口与实现
3、面向对象的设计原则你知道有哪些吗
单一职责原则(SRP)一个类应该只有一个引起它变化的原因即一个类应该只负责一项职责。例子:考虑一个员工类它应该只负责管理员工信息而不应负责其他无关工作。开放封闭原则(OCP):软件实体应该对扩展开放对修改封闭。例子:通过制定接口来实现这一原则比如定义一个图形类然后让不同类型的图形继承这个类而不需要修改图形类本身。里氏替换原则(LSP):子类对象应该能够替换掉所有父类对象。例子:一个正方形是一个矩形但如果修改一个矩形的高度和宽度时正方形的行为应该如何改变就是一个违反里氏替换原则的例子。接口隔离原则(ISP):客户端不应该依赖那些它不需要的接口即接口应该小而专。例子:通过接口抽象层来实现底层和高层模块之间的解耦比如使用依赖注入。依赖倒置原则(DIP):高层模块不应该依赖低层模块二者都应该依赖于抽象;抽象不应该依赖于细节细节应该依赖于抽象。例子:如果一个公司类包含部门类应该考虑使用合成/聚合关系而不是将公司类继承自部门类。
4、重载与重写有什么区别? 重载(Overloading)指的是在同一个类中可以有多个同名方法它们具有不同的参数列表参数类型、:参数个数或参数顺序不同)编译器根据调用时的参数类型来决定调用哪个方法。 重写(Overriding)指的是子类可以重新定义父类中的方法方法名、参数列表和返回类型必须与父类中的方法一致通过override注解来明确表示这是对父类方法的重写。 重载是指在同一个类中定义多个同名方法而重写是指子类重新定义父类中的方法。
5、深拷贝和浅拷贝的区别
一、浅拷贝 1、定义
指创建一个新的对象这个新的对象会复制原对象中的所有非引用类型的数据如基本数据类型而对于引用类型的数据如对象、数组只会复制引用地址而进行引用与原来对象指向同一个对象。
2.、特点
基本数据类型复制的是值。引用数据类型复制的是引用地址。
二、深拷贝Deep Copy 1、定义 深拷贝是指创建一个新的对象这个新的对象会复制原对象中的所有数据无论是基本数据类型还是引用数据类型都会创建新的副本而不是共享引用地址。
2、特点
基本数据类型复制的是值。引用数据类型复制的是引用所指向的实际数据而不是引用地址。
6、实现深拷贝的三种方法是什么
实现 Cloneable 接口并重写 clone() 方法使用序列化和反序列化手动递归复制
7、 什么是泛型
泛型Generics是编程语言中的一种特性允许在定义类、接口和方法时使用类型参数。这些类型参数在实际运行时会被具体的类型替换从而使代码更加灵活和复用。
8、java创建对象有哪些方式
new关键字使用Class.newInstance()方法 反射在运行时动态创建对象适用于需要灵活性的场景。工厂方法通过工厂类创建对象适用于需要统一管理对象创建的场景。单例模式确保一个类只有一个实例适用于需要全局唯一实例的场景。克隆方法创建对象的副本适用于需要复制对象的场景。对象反序列化从字节流中恢复对象适用于需要持久化对象的场景。
9、什么是反射
在运行状态中动态获取类的所有信息包括属性方法等以及动态调用对象的方法和动态生成对象。
10、有什么异常分为什么类型
Error错误Exception异常 非运行异常运行时异常RuntimeException常见有空指针NullPointerException数组越界ArrayIndexOutOfBoundsException
11、 与 equals 有什么区别
比较的是两个字符串的内存地址equals比较的是两个字符串的内容
12、StringBuffer和StringBuild区别是什么
StringBuffer线程安全StringBuild线程不安全速度快
13、completableFuture是什么的
CompletableFuture对Future进行了扩展可以通过设置回调的方式处理计算结果同时也支持组合操作支持进一步的编排同时一定程度解决了回调函数的问题。
14、怎么把一个对象从一个jvm转移到另一个jvm?
序列化和反序列化消息传递机制
二、Java集合篇
1、说说Java中的集合
1List有序集合
ArrayList动态数组底层是基于数组实现的当扩容时候会创建更大的数组并把原数组复制到新数组。LinkedList本质是一个双向链表与ArrayList相比其插入和删除速度更快但随机访问速度更慢。
2Set无序唯一不允许存在重复的元素与List不同Set中的元素是无序的。常用的实现有HashSetLinkedHashSet和TreeSet。
HashSet通过HashMap实现使用HashMap的Key 存储的元素所有Key都是用相同的Value这样Key保证了唯一性但不保证有序性。由于HashSet是HashMap实现的因此线程不安全。LinkedHashSet继承自HashSet通过LinkedHashMap实现使用双向链表维护元素插入顺序。TreeSet通过TreeMap实现的添加元素到集合时按照比较规则将其插入合适的位置保证插入后的集合仍然有序。
3Map 是一个键值对集合Key 无序唯一;value 不要求有序允许重复。Map 没有继承于 Collection 接口从 Map 集合中检索元素时只要给出键对象就会返回对应的值对象。主要实现有TreeMap、HashMap.HashTable、LinkedHashMap、ConcurrentHashMap。
HashMap:JDK1.8之前HashMap主要由数组链表构成数组是HashMap主体。
2、Java中的线程安全的集合是什么
Vector线程安全的动态数组其内部方法基本都经过synchronized修饰Hashtable:线程安全的哈希表加锁的方式是给每个方法加锁导致所致的是整个Table对象。ConcurrentHashMap:它与HashTable的主要区别是二者加锁力度不同。JDK1.7加的是分段锁也就是所谓的Segment锁每个Segment锁含有整个table的一部分这样不同分段之间的并发操作就互不影响。在JDK1.8他取消了Segment字段直接在table元素上锁实现对每一行进行加锁进一步减少了并发冲突ConcurrentSkipListSet。CopyOnWriteArraySetCopyOnWriteArrayList
3、Collections和Collection的区别
4、为什么ArrayList不是线程安全的具体来说是哪里不安全
高并发添加数据下
部分值为null索引越界异常size与我们add的数量不符
5、ArrayList的扩容机制说一下
6、线程安全的 List CopyonWriteArraylist是如何实现线程安全的
7、HashMap的底层原理介绍一下
JDK1.7 JDK1.8优化了1.7中数组扩容的方案解决了Entry链表死循环和数据丢失问题就是把尾插法变成了头插法
8、了解的哈希冲突解决方法有哪些
9、hashmap的put过程介绍一下
7、扩容操作
创建一个新的两倍大小的数组。将旧数组中的键值对重新计算哈希码并分配导新数组中的位置。
10、ConcurrentHashMap怎么实现的
JDK1.7 JDK1.8
11、ConcurrentHashMap用了悲观锁还是乐观锁?
12、HashTable 底层实现原理是什么
13、Set集合有什么特点如何实现key无重复的
Set集合特点Set集合中的元素是唯一的不会出现重复的元素且是无序的。Set实现原理Set集合底层是哈希表通过hashCode值来确定元素的存储位置然后通过equals方法判断是否已经存在相同的元素如果存在不插入保证了元素的唯一性。
14、有序的Set是什么记录插入顺序的集合是什么
TreeSet基于红黑树实现保证元素的自然顺序。LinkedHashSet基于双重链表和哈希表的结合来实现元素的有序存储保证元素添加的自然顺序
三、Java并发篇
1、Java的线程安全在三个方面的体现
原子性可见性有序性
2、保证数据的一致性有哪些方案呢
事务管理锁机制版本控制可以通过乐观锁的方式在更新数据时记录数据的版本信息从而避免同时对同一数据进行修改进而保证数据的一致性。
3、线程的创建方式有哪些?
继承Thread类
class MyThreadextends Thread {override
public void run(){
//线程执行的代码
public static void main(string[] args){MyThread t new MyThread();t.start();实现Runable接口
class MyRunnable implements Runnable {override
public void run(){
// 线程执行的代码
public static void main(string[] args){
Thread t new Thread(new MyRunnable());t.start();实现Callable接口与FutureTask
class MyCallable implements callableInteger
override
public Integer call()throws Exception {//线程执行的代码这里返回一个整型结果return 1;
public static void main(string[] args){MyCallable task new MyCallable();FutureTaskIntegerfutureTask new FutureTask(task);Thread t new Thread(futureTask);t.start();
try {
Integer result futureTask.get(); // 获取线程执行结果System.out.println(Result: result);}catch(InterruptedExceptionExecutionException e){e.printstackTrace();使用线程池
4、Java线程的状态有哪些
New尚未启动的线程状态即所谓的线程创建还未调用start方法RUNNABLE就绪状态已经调用start等待调度正在运行BLOCKED获取锁失败陷入阻塞状态WAITING等待状态的线程正在等待另一个线程执行完毕TIMED_WAITING具有指定等待时间的等待状态TERMINATED线程终止状态。
5、wait 状态下的线程如何进行恢复到 running 状态?
等待的线程被其他线程对象唤醒notify()和notifyAll()
6、如何保证多线程安全
使用synchronized关键字volatile关键字保证变量对所有线程都是可见的Lock接口和ReentrantLock类。线程局部变量:ThreadLocal线程变量副本。并发集合
7、Java中有哪些常用的锁
内置锁synchronizedReentrantLock读写锁ReadWriteLock允许多个读取中同时访问共享资源但是只允许一个写入者乐观锁和悲观锁自旋锁
8、synchronized和reentrantlock的工作原理
1、synchronized工作原理 使用synchronized之后会在编译之后在同步的代码块前后加上monitorenter和monitorexit字节码指令它依赖操作系统底层互斥锁实现。他的作用主要就是实现原子性操作和解决共享变量的内存可见性问题。 执行monitorenter指令时会尝试获取对象锁如果对象没有被锁定或者已经获得了锁锁的计数器1。此时其他竞争锁的线程则会进入等待队列中。执行monitorexit指令时则会把计数器-1当计数器值为0时则锁释放处于等待队列中的线程再继续竞争锁。 synchronized是排它锁当一个线程获得锁之后其他线程必须等待该线程释放锁后才能获得锁而且由于Java中的线程和操作系统原生线程是-一对应的线程被阻塞或者唤醒时时会从用户态切换到内核态这种转换非常消耗性能。 从内存语义来说加锁的过程会清除工作内存中的共享变量再从主内存读取而释放锁的过程则是将工作内存中的共享变量写回主内存。 实际上大部分时候我认为说到monitorenter就行了但是为了更清楚的描述还是再具体一点。 如果再深入到源码来说synchronized实际上有两个队列waitSet和entryList。 1.当多个线程进入同步代码块时首先进入entryList 2.有一个线程获取到monitor锁后就赋值给当前线程并且计数器1。 3.如果线程调用wait方法将释放锁当前线程置为nul计数器-1同时进入waitset等待被唤醒调用notify或者notifyAll之后又会进入entryList竞争锁 4.如果线程执行完毕同样释放锁计数器-1当前线程置为null。
2、Reentranlock工作原理
9、详细介绍一下Java中的waitjoinsleep方法
wait() 方法 wait() 方法是 Object 类中的一个方法任何对象都可以调用该方法。它用于使当前线程进入 等待状态并释放当前对象的锁。wait() 必须在同步方法或同步代码块中调用。
主要特性 释放锁调用 wait() 后当前线程释放对该对象的锁并且进入等待队列中直到被其他线程唤醒。 唤醒机制当前线程被唤醒后通过 notify() 或 notifyAll()会重新争夺该对象的锁才能继续执行。 使用场景wait() 方法常用于实现线程间的协调机制例如生产者-消费者模式、线程间的同步等。
join() 方法 join() 方法是 Thread 类中的方法作用是让当前线程等待调用 join() 方法的线程执行完毕。换句话说它会让当前线程 加入到其他线程 的执行中当前线程会等待被调用线程结束后再继续执行。
主要特性 线程等待调用 join() 后当前线程会等待目标线程执行完毕当前线程才会继续执行。 没有锁机制join() 方法不涉及锁机制主要是线程的执行顺序控制。 使用场景join() 常用于在多线程环境中需要等待某个线程完成后再继续执行其他操作的场景。
sleep() 方法 sleep() 是 Thread 类中的静态方法用于让当前线程 休眠指定的时间在此期间当前线程不占用 CPU 资源。
主要特性 不释放锁sleep() 只是让当前线程暂停执行指定的时间不会释放持有的锁。 精确度sleep() 的时间精度不一定很高它是由操作系统来调度的因此有可能在超时时间之前或之后被唤醒。 使用场景sleep() 主要用于让线程暂停一段时间例如定时任务、控制线程执行间隔等。
10、synchronized和Reentrantlock区别
共同点
都是可重入锁都能保证数据的一致性
不同点
用法不同synchronized可用来修饰方法、代码块而Reentrantlock只能用在代码块上。获取锁和释放锁方式不同synchronized会自动加锁和释放锁当进入synchronized修饰的代码块之后就会自动加锁当离开代码块时候自动释放锁。而Reentrantlock需要手动加锁和释放锁。锁类型不同synchronized属于非公平锁而 ReentrantLock 既可以是公平锁也可以是非公平锁。响应中断不同ReentrantLoeck 可以响应中断解决死锁的问题而 synchronized 不能响应中断底层实现不同synchronized 是JVM层面通过监视器实现的而ReentrantLoeck 是基于AQS实现的。
11、如何理解可重入锁
可重入锁指的是同一个线程在获取了锁之后可以再次重复获取该锁而不会造成死锁或者其他问题。
12、ReentrantLock和synchronized 如何实现可重入锁的
1、ReentrantLock
ReentrantLock实现可重入锁的机制是基于线程持有锁的计数器。 当一个线程第一次获取锁时计数器会1表示该线程持有了锁。在此之后如果同一个线程再次获取锁计数器会再次加1。每次线程成功获取锁时都会将计数器加1。当线程释放锁时计数器会相应地减1。只有当计数器减到0时锁才会完全释放其他线程才有机会获取锁。 这种计数器的设计使得同一个线程可以多次获取同一个锁而不会造成死锁或其他问题。每次获取锁时计数器加1;每次释放锁时计数器减1。只有当计数器减到0时锁才会完全释放。 ReentrantLock通过这种计数器的方式实现了可重入锁的机制。它允许同一个线程多次获取同一个锁并且能够正确地处理锁的获取和释放避免了死锁和其他并发问题。
2、synchronized 在底层实现上synchronized 锁的重入性通过 锁的计数器 来实现。每当一个线程获取锁时锁的计数器就增加 1。当该线程释放锁时计数器减 1。只有当计数器减到 0 时其他线程才能获得锁。
13、syncronized锁升级的过程讲一下
详细了解锁升级过程请前往https://blog.csdn.net/a147775/article/details/141461091
14、什么是AQS和CAS
1、AQS AQS 是 java.util.concurrent 包中的一个抽象类用于构建同步器锁。它为实现各种同步机制如锁、信号量、读写锁等提供了基础框架。 它的主要核心思想通过队列化等待线程和原子状态更新来实现同步控制。
2、CAS CAS 是一种原子操作,它主要有三个操作数内存地址、旧值、新值。主要作用就是比较内存中的值与旧值是否相等如果相等就将内存中的值更新为新增。
3、总结 AQS提供了一个基础框架用于实现自定义同步器。它管理线程的等待队列和同步状态支持多种同步机制的实现。 CAS是一种无锁的原子操作用于原子地比较和更新内存中的值广泛用于构建无锁数据结构和高效的并发控制。
15、Threadlocal作用原理具体里面存的key value是啥会有什么问题如何解决?
详细了解请前往https://blog.csdn.net/a147775/article/details/141723123
16、悲观锁和乐观锁的区别
乐观锁乐观锁认为不会有数据竞争发生对数据不进行加锁操作而是通过一些机制如版本号、时间戳等检查是否发生了冲突如果发生冲突则回滚或者进行重试操作。悲观锁认为数据竞争会发生始终加锁防止并发冲突。
17、Java中想实现一个乐观锁都有哪些方式
CAS操作版本号控制时间戳
18、CAS 有什么缺点
ABA问题更新时候读取到的是A值然后准备进行赋值时候仍然是A实际是A-B-A这个过程了循环时间开销大自旋CAS的方式如果长时间不成功会给CPU带来很大的开销只能保证一个共享变量的原子操作只对一个共享变量操作可以保证原子性多个就不行。
19、voliatle关键字有什么作用
保证变量对所有线程的可见性禁止指令重排序
20、什么是公平锁和非公平锁
1、公平锁Fair Lock
公平锁的基本概念是线程按请求锁的顺序来获取锁即 先进先得First Come, First Served。在公平锁中先请求锁的线程会先获得锁后请求的线程必须等到前面的线程释放锁后才能获取锁避免线程饥饿。
2、非公平锁Non-fair Lock
非公平锁的基本概念是线程不严格按照请求锁的顺序获取锁即任何线程都可以抢先获得锁。在非公平锁的策略中如果锁当前没有被占用任何线程都可以尝试获取锁即使它们不是按请求顺序来的。非公平锁通常会优先让等待时间较短的线程或者刚进入的线程获取锁而不是按照队列中的顺序来。
21、介绍一下线程池的工作原理
线程池中始终存在着核心线程数提交任务时候会分配核心线程去执行如果核心线程都在处理任务此时加入任务就会将任务加入到等待队列如果核心线程数始终在执行其他任务任务一直在提交直到等待队列满了此时会增加线程如果达到最大线程数再有任务提交就会执行一些丢弃的任务策略
22、线程池的参数有哪些
核心线程数corePoolSize最大线程数maximumPoolSize空闲线程存活时间keepAliveTimeUnit存活时间单位任务队列workQueue线程工厂threadFactory拒绝策略rejectedExecutionHandler
23、线程池工作队列满了有哪些拒接策略
AbortPolicy默认策略抛出 RejectedExecutionException 异常拒绝执行新任务。CallerRunsPolicy使用线程池的调用者所在的线程去执行被拒绝的任务DiscardPolicy直接丢弃任务不做任何处理。DiscardOldestPolicy丢弃队列中最旧的任务提交当前任务。
24、线程池种类有哪些
1、Fixed Thread Pool固定大小线程池
FixedThreadPool 是一种固定大小的线程池。它创建的线程数固定线程池中的线程数量不会动态调整。无论任务的数量如何线程池中始终保持着相同数量的线程来处理任务。如果线程池中有线程处于空闲状态它将等待新任务的到来。如果任务数超出了线程池的处理能力任务将被放入任务队列中等待。 适用场景线程数量固定、任务量较为均匀且系统负载不希望波动的情况 示例 public static void main(String[] args) {// 创建一个固定大小为 3 的线程池ExecutorService executor Executors.newFixedThreadPool(3);// 提交任务for (int i 0; i 5; i) {executor.submit(() - {System.out.println(Thread.currentThread().getName() is executing task);});}// 关闭线程池executor.shutdown();}2、 Cached Thread Pool缓存线程池
CachedThreadPool 是一种能够根据需求自动扩展的线程池。线程池中的线程数量是动态变化的如果线程池中有空闲线程它会复用这些线程来执行任务。如果所有的线程都在忙碌线程池会创建新的线程来处理任务。当线程空闲超过一定时间默认 60 秒它们会被回收。 适用场景任务执行时间短且任务量不确定的场景适合高并发的任务但不会造成线程过多的系统资源浪费。 示例
public static void main(String[] args) {// 创建一个固定大小为 3 的线程池ExecutorService executor Executors.newCachedThreadPool();// 提交任务for (int i 0; i 5; i) {executor.submit(() - {System.out.println(Thread.currentThread().getName() is executing task);});}// 关闭线程池executor.shutdown();}3、Single Thread Executor单线程池
SingleThreadExecutor 是一种只有一个工作线程的线程池。这个线程池用于确保只有一个线程执行任务。所有提交的任务会按照顺序一个一个执行不会并行执行。如果这个唯一的工作线程异常终止线程池会创建一个新的线程来代替它。 适用场景任务需要按顺序执行且不希望并发执行适用于顺序依赖的任务或者需要保证任务执行顺序的场景。 4、 Scheduled Thread Pool定时任务线程池
ScheduledThreadPoolExecutor 是一种支持定时任务和周期性任务的线程池。它不仅可以执行定时任务还可以周期性地执行任务比如每隔一段时间执行一次任务。它的主要用途是执行延迟任务或定时任务。 适用场景需要延迟执行或者定时执行任务的场景例如定时清理缓存、定期检查系统健康状态等。 5、Custom Thread Pool自定义线程池
除了使用 Executors 提供的线程池外Java 也允许开发者根据业务需求自定义线程池。通过 ThreadPoolExecutor 构造器可以手动配置线程池的参数制定核心线程数、最大线程数、任务队列、线程工厂和拒绝策略等。
总结
FixedThreadPool固定数量的线程池适用于任务量稳定且线程数固定的场景。 CachedThreadPool可根据需求动态扩展线程数适用于任务执行时间短且任务量不确定的场景。 SingleThreadExecutor只有一个线程的线程池适用于需要按顺序执行的场景。 ScheduledThreadPoolExecutor定时和周期性任务线程池适用于定时任务。 ThreadPoolExecutor自定义线程池允许开发者根据具体业务需求配置线程池。
四、SpringSpringBootSpringCloud篇
1、Spring框架的核心特性有什么
IOC容器Spring通过控制反转实现了对象的创建和依赖关系的管理。AOP面向切面编程。事务管理MVC框架采用了模型-视图-控制器架构。
2、Spring IOC、Spring IOC容器分别是什么二者有何区别
1、IOC 它是Spring框架的核心概念之一翻译为控制反转。它是一种设计原则思想意味着创建对象控制权的转移。在传统的编程模式下对象的创建和管理都是通过程序员进行控制但在IOC中是通过容器来创建和管理对象的生命周期和依赖关系从而实现了控制权的反转。
关键特性
反转控制程序员不再手动创建对象和处理依赖关系Spring 容器会根据配置来创建对象并注入其所依赖的其他对象。依赖注入DIIOC 容器通过依赖注入的方式将对象的依赖关系自动注入而不需要显示地通过代码来创建依赖对象。
2、IOC容器 它是 Spring 框架中用于实现IOC设计思想的核心组件它是一个用来管理Spring 应用程序中对象的创建、管理对象的生命周期以及处理对象间依赖关系的容器 Spring 提供了两种主要的 IOC 容器
BeanFactory最简单的容器提供了基本的 IOC 功能。它在创建 Bean 时是懒加载的。 ApplicationContext是 BeanFactory 的扩展提供了更多的功能如事件传播、国际化支持等通常应用于实际开发中。
3、总结 Spring IOC 是一种设计思想和设计模式它描述了如何将对象的创建和依赖关系交给容器来管理以实现松耦合。 Spring IOC 容器 是 Spring 框架中实现该设计模式的核心组件负责管理应用程序中的对象和其生命周期、依赖注入等操作。
3、Spring AOP介绍一下
AOP是一种面向切面编程思想它能够将那些与业务无关却为业务模块锁共同调用的逻辑封装起来便于减少系统中的重复代码降低模块间的耦合度并有利于未来的可扩展性和可维护性。
常用的注解包括
Aspect:用于定义切面标注在切面类上。Pointcut:定义切点标注在方法上用于指定连接点。。Before:在方法执行之前执行通知。After:在方法执行之后执行通知Around:在方法执行前后都执行通知。AfterReturning:在方法执行后返回结果后执行通知。AfterThrowing:在方法抛出异常后执行通知。Advice:通用的通知类型可以替代Before、After等。
4、IOC和AOP是通过什么机制来实现的?
一、Spring IOC实现机制
反射通过反射机制动态的创建对象。依赖注入通过构造函数方法注入属性注入或者方法注入依赖对象。设计模式-工厂模式容器实现Spring lOC容器是实现IOC的核心通常使用BeanFactory或ApplicationContext来管理Bean。Beanfactory是IOC容器的基本形式提供基本的IOC功能:ApplicationContext是BeanFactory的扩展并提供更多企业级功能。
二、Spring AOP实现机制
Spring AOP的实现依赖于动态代理技术。动态代理是在运行时动态生成代理对象而不是在编译时从而实现在不修改源码的情况下无侵入式增强方法的功能。
Spring AOP支持两种动态代理
基于JDK的动态代理代理类实现一个或者多个接口CGLIB动态代理代理类没有实现接口可以使用CGLIB库生成一个被代理类的子类作为代理。CGLIB是一个第三方代码生产库通过继承方式实现代理。
5、静态代理和动态代理的区别是什么
静态代理由程序员本身是实现某个接口创建在代码编译时就被确定了被代理的类是一个静态代理。动态代理在运行时利用反射机制动态生成代理对象。
6、spring是如何解决循环依赖的以及循环产生的原因是什么
Bean相互依赖造成死循环的原因
假设没有三级缓存机制或其他机制来解决循环依赖创建过程会是这样
Spring 初始化 A发现 A 需要 B于是开始实例化 B。 Spring 初始化 B发现 B 需要 A但 A 还没有创建完成因此 Spring 无法继续创建 B也无法返回到创建 A。 死锁A 和 B 互相等待对方完成实例化因此无法继续导致实例化过程无法完成。 总的来说就是相互依赖时Spring无法确定哪个Bean应该先创建导致实例化过程陷入死锁。
循环依赖产生无非就是所谓的A依赖B然后B依赖A最后导致循环依赖。 主要情况通过setter方法进行依赖注入在单例模式下产生的循环依赖问题。
解决单例模式下的循环依赖问题主要方式通过三级缓存依赖解决。
7、Spring三级缓存是什么过程是怎么样的
Spring 三级缓存机制是 Spring IoC 容器在处理单例 Bean 创建时的一个优化机制它通过三级缓存singletonObjects、earlySingletonObjects、singletonFactories管理 Bean 的不同生命周期阶段以解决循环依赖和提升性能。
其中三级缓存包含的三个缓存 1、singletonObjects存放已经完全初始化的单例Bean。 2、earlySingletonObjects存放还未完成初始化但已经实例化的单例Bean用于早起暴露引用避免循环依赖。 3、singletonFactories存放用来创建Bean的工程实际上一个ObjectFactory它在实例化是提供创建Bean的逻辑。
对于A依赖BB依赖A通过三级缓存解决循环依赖过程 1、创建 Bean A
Spring 在创建 A 时发现 A 依赖于 B于是开始创建 B。 2、创建 Bean B
在创建 B 时Spring 发现 B 也依赖于 A因此产生循环依赖。此时Spring 会将 B 实例的工厂ObjectFactory放入 singletonFactories 中。 此时Spring 会将 B 的早期引用放入 earlySingletonObjects 中表示 B 已实例化但还没有完成初始化例如依赖注入和生命周期回调还未完成。
3、A 依赖 B
当 A 继续创建时Spring 会发现 A 依赖于 B此时 B 已经实例化但尚未完成初始化。Spring 会从 earlySingletonObjects 中获取 B 的早期引用完成 A 的实例化。 完成 Bean 初始化
4、A在实例化完成后
将注入到B最终A 和 B 会被完全初始化并被放入 singletonObjects 缓存中。
5、清理缓存
一旦 A 和 B 完全初始化earlySingletonObjects 和 singletonFactories 缓存中的数据会被清理避免内存泄漏。
8、Spring三级缓存的数据结构是什么
都是Map类型keybean的名称vaule实例
9、Spring框架中都用到了哪些设计模式
工厂模式单例模式代理模式
10、Spring、Spring MVC、Spring Boot常用的注解
1、Spring Component标记一个类为 Spring 管理的 BeanSpring 会自动扫描并将其注册为一个 Bean。 Service表示一个服务层的组件实际上是 Component 的一种特化通常用于标识服务层的业务逻辑类。 Repository表示一个数据访问层的组件表示该类为 DAOData Access Object层的组件用于数据库操作。 Controller用于定义一个控制器类处理请求。 Configuration标识一个配置类通常用于替代传统的 XML 配置文件。 Bean用于在 Java 配置类中定义一个 Bean类似于 XML 配置中的 元素。 Autowired自动注入依赖的 Bean可以注入到字段、构造函数、方法上。
2、Spring MVC RequestMapping映射 HTTP 请求到指定的方法或类上支持 GET, POST 等请求类型。通常用于 Spring MVC 控制器类的方法。 GetMapping用于处理 HTTP GET 请求的快捷方式。 PostMapping用于处理 HTTP POST 请求的快捷方式。 PutMapping用于处理 HTTP PUT 请求的快捷方式。 DeleteMapping用于处理 HTTP DELETE 请求的快捷方式。 RequestParam用于从请求中获取参数可以用于方法参数上来获取请求中的查询参数或表单参数。 PathVariable用于从 URL 路径中获取动态参数。
RequestBody用于将 HTTP 请求体中的数据映射到 Java 对象。 ResponseBody用于将方法的返回值直接写入 HTTP 响应体中通常用于返回 JSON 或 XML 格式的数据。 RestControllerAdvice全局异常处理可以定义多个异常处理方法来处理不同的异常类型。通过 ExceptionHandler 注解方法会捕获指定的异常并返回相应的错误信息。 ExceptionHandler用于定义异常处理方法处理控制器方法中抛出的异常。
11、Spring生命周期中的实例化和初始化阶段有何区别
1、实例化 创建 Bean 实例的过程。Bean 的构造函数被调用Spring 通过反射生成对象但还没有进行任何的依赖注入、配置或初始化工作。
2、初始化实例化完成后Spring 对 Bean 进行依赖注入在依赖注入完成后Spring 会调用 PostConstruct 注解标记的方法。此时Bean 已经准备好可以使用并且可以进行一些后续的配置和资源初始化。
总结 实例化 仅仅是创建一个 Bean 对象它没有进行任何依赖注入或其他配置。
初始化 是 Bean 生命周期中的一个重要阶段发生在实例化之后依赖注入完成后Spring 会执行初始化方法对 Bean 进行必要的配置和初始化操作。
12、Spring 中Bean的生命周期说一下
进行实例化通过反射机制创建Bean。依赖注入: 将容器中的依赖注入到Bean中。初始化执行初始化回调方法。可用Bean可用于服务销毁容器关闭执行销毁回调方法。
生命周期示意图 ----------------------| Bean 实例化 |----------------------|v----------------------| 依赖注入 |----------------------|v----------------------| 初始化PostConstruct |----------------------|v----------------------| Bean 可用阶段 |----------------------|v----------------------| 销毁PreDestroy |----------------------
13、Spring bean的作用域有哪些
单例Singleton原型Prototype会话Session请求Request
14、MVC分层介绍一下
MVC分层介绍一下 MVC全名是Model View Controller是模型(model)-视图(view)-控制器(controller)的缩写一种软件设计典范。
模型存取数据的地方。视图与用户直接进行交互界面的地方。控制器用于将用户请求转发给对应的Model处理的地方。
15、为什么使用springboot比Spring好在哪里 简化配置 在传统的 Spring 项目中你需要大量的 XML 配置或者在 Java 配置中通过注解进行配置。这不仅复杂且容易出错还需要开发人员手动进行许多冗长的配置工作。Spring Boot 的出现大大简化了这一步骤 快速启动快速开发Spring Boot中提供了许多个start模块并且还内嵌了服务器Tomcat 开箱即用的功能
16、SpringBoot自动装配原理是什么
自动装配的核心是EnableAutoConfiguration注解 EnableAutoConfiguration启用自动装配。 ComponentScan启用组件扫描自动扫描当前包及其子包中的 Spring 组件如 Component、Service、Repository 等。 Configuration指示该类是一个 Spring 配置类。
SpringBoot的自动配置原理是通过EnableAutoConfiguration注解实现这个注解包含Import({AutoConfigurationImportSelector.class})注解导入的这个类会去扫描 classpath下所有的METAINE/spring.factories中的文件根据文件中指定的配置类加载相应的 Bean 的自动配置。 这 些Bean通常会使用Conditional这是一个核心注解用来根据条件来决定是否创建某个 Bean等条件注解。来控制自动配置的加载条件例如仅在类路径中存在某个类时才加载某些配置。
17、Mybatis里的 #{} 和 ${} 的区别
#{}在运行时会传机预编译的SQL语句将SQL中的#{}替换成可防止SQL注入。
${}只是普通的SQL语句然后再执行SQL语句时Mybatis将参数直接拼到SQL里不能防止SQL注入。
18、负载均衡有哪些算法
简单轮询将请求按顺序分发给后端服务器上不关心服务器当前的状态。加权轮询根据服务器自身的性能给服务器设置不同的权重。简单随机将请求随机分发给后端服务器请求越多各个服务器接收到的请求越平均。加权随机根据服务器自身的性能给服务器设置不同的权重将请求按各个服务器的权重随机分发给后端服务器。一致性哈希最小活跃数
五、MySQL篇
1、数据库三大范式是什么
1NF数据库的每一列都是不可分割的原子数据项。2NF在1NF基础上非码属性必须完全依赖于候选码。即为每一列都必须和主键相关。3NF在2NF基础上任何非主属性不依赖于其他非主属性。即为需要确保数据表中的每一列数据都和主键直接相关而不能间接相关。
2、MySQL 怎么连表查询
内连接左外连接右外连接全连接
3、MySQL如何避免重复插入数据
使用唯一键约束使用INSERT IGNORE使用INSERT … ON DUPLICATE KEY UPDATE
4、CHAR 和 VARCHAR有什么区别
CHAR 是固定长度的字符串类型定义时需要指定长度存储不够时会在末尾补足空格。 VARCHAR 是可变长度的字符串类型定义时需要指定最大长度实际存储根据实际长度占用空间计算。
5、mysql中的一些基本函数你知道哪些
1、字符串
CONCAT合并字符串LENGTH计算字符串长度SUBSTRING截取字符串
2、日期和时间
NOW():返回当前日期和时间。CURDATE():返回当前日期。
3、聚合函数
COUNT(column)计算指定列中的非NULL值的个数。SUM(column)计算指定列的总和。AVG(column)计算指定列的平均值。MAX(column)返回指定列的最大值。MIN(column)返回指定列的最小值。
6、SQL查询语句的执行顺序是如何的
先通过连接器校验权限利用分析器进行SQL语句的词法分析和语法分析构建解析树使用优化器选择合适的索引和表连接顺序最终选择一个最佳的执行计划利用执行器调用引擎层查询数据返回结果集给客户端。
7、MySQL引擎有哪些你有什么了解
InnoDBInnoDB是MySQL的默认存储引擎具有ACID事务支持、行级锁、外键约束等特性使用于高并发的读写操作支持较好的数据完整性和并发控制。MyISAM:MyISAM是MySQL的另一种常见的存储引擎具有较低的存储空间和内存消耗适用于大量读操作的场景。然而MISAM不支持事务、行级锁和外键约束因此在并发写入和数据完整性方面有一定的限制。Memory:Memory引擎将数据存储在内存中适用于对性能要求较高的读操作但是在服务器重启或崩溃时数据会丢失。它不支持事务、行级锁和外键约束。
8、MySQL的InnoDB与MyISAM的区别
锁InnoDB支持最小粒度的行级锁MyISAM不支持只支持表锁。索引结构InnoDB是聚簇索引MyISAM是非聚簇索引。事务InnoDB支持事务MyISAM不支持
9、索引的分类是什么
可从四个角度来分类索引。
按数据结构分类BTree索引、Hash索引、倒排索引。按物理存储分类聚簇索引、二级索引。按字段特性分类主键索引、唯一、普通、前缀索引。按字段个数分类单列索引、联合索引
10、MySQL聚簇索引和非聚簇索引的区别是什么
存储位置聚簇索引的叶子节点包含了实际的数据行而非聚簇索引的叶子节点不包含完整的数据行。索引与数据关系通过聚簇索引查找数据可以直接从索引中获取数据行。非聚簇索引则需要找到对应的主键值然后通过主键值回溯到聚簇索引中才能查找到数据也就是所谓的回表查询。查询效率聚簇索引更快非聚簇索引需要进行回表查询数据比较慢。
聚簇索引示意图 非聚簇索引示意图
11、索引失效有哪些
对索引列使用函数对索引列进行表达式计算参数是字符串输入是数字类型导致的隐式类型转换进行模糊匹配主要方式是%xx 或者%x%联合索引最左匹配原则失效where条件中or前条件是索引列后不是索引失效。
12、什么情况回进行回表查询
查询的数据在二级索引中查询不到就需要进行回表查询。
13、什么是覆盖索引
覆盖索引指的是一个索引包含了所需的所有列不需要进行回表查询数据行就能完成查询。
14、如何进行索引优化
尽量进行覆盖索引避免回表查询。使用前缀索引主键自增防止页分裂防止索引失效
15、事务的特性是什么详细说说
原子性A要么所有操作完成要么回滚一致性C)事务操作前后数据库的数据保持一致状态。隔离性I允许多个并发事务对数据进行读写和修改不会互相干扰。持久性D数据进行持久化到磁盘不会丢失。 MySQL是如何保证这四个特性的原子性通过undo log回滚日志保证持久性通过redo log重做日志。隔离性MVCC和锁机制一致性上述三个保证
16、MySQL中什么是脏读不可重复读幻读
1、脏读 一个事务读到了另外一个未提交事务修改的数据。 2、不可重复读 一个事务多次读取同一个数据出现前后两次读到的数据不一致的情况。 3、幻读 一个事务多次查询某个符合条件的记录数量结果出现前后两次查询到的记录数量不一样的情况。
17、对于并发问题mysql有什么方法解决
MVCC事务隔离锁机制
18、事务的隔离级别有哪些
读未提交读提交可解决脏读问题可重复读可解决脏读不可重复读问题串行化可解决脏读不可重复读幻读
19、MySQL默认的隔离级别是什么?
可重复读
20、MVCC是什么
MVCC是一种多版本并发控制机制允许多个事务同时读取和写入数据库而无需相互等待从而提高数据库的并发性能。 实现原理 数据库为每个事务创建一个数据快照。每当数据被修改时MySQL不会立即覆盖原有数据而是生成新版本的记录。每个记录都保留了对应的版本号或时间戳。通过多版本之间串联起来形成了一条版本链这样不同时刻启动的事务都可以无锁地获得不同版本的数据。
21、MysSQL中有哪些锁 全局锁 表级锁 表级锁对整个表进行加锁其他事务无法对该表进行任何读写操作。 表共享读锁lock tables 表明 read当前客户端和其他客户端都只能进行读操作。表独占写锁lock tables 表明 write当前客户端读写都可以进行其他客户端读写操作均不可进行 元数据锁MDL)维护开启事务后每个客户端的sql操作主要是为了避免DML和DDL操作的冲突。 MDL读锁CRUD关键字都会上锁。MDL写锁改变表结构时候alter table上锁MDL读锁互斥。 意向锁为了避免DML执行时解决行锁与表锁的冲突使得表锁不用检查每行数据是否加了锁使用意向锁来减少表锁的检查。需要开启事务。 行级锁重点 行级锁也称记录锁仅对特定的行加锁允许其他事务并发访问不同的行 共享锁**S 重点**允许多个事务并发读取同一资源但不允许修改。排他锁 X 重点只允许一个事务对资源进行读写其他事务在获得排他锁之前无法访问资源 间隙锁**重点**针对索引中两个记录之间的间隙加锁防止其他事务在这个间隙中插入新记录从而防止出现幻读。临键锁**重点**行级锁和间隙锁的结合锁定具体行和其前面的间隙确保在一个范围内不会出现幻读。常用于支持可重复读的隔离锁级别
22、日志文件是分成了哪几种
redo log重做日志实现了事务的持久性undo log回滚日志实现了事务的原子性主要用于事务回滚和MVCCbin log二进制日志主要用于数据备份和主从复制。relay log中继日志用于主复制场景
23、MySQL中explain有什么作用并详细说说它的参数
用来查看sql语句的执行计划分析sql语句的执行过程判断是否有走索引等等。
其中主要参数
possible_keys 字段表示可能用到的索引;key 字段表示实际用的索引如果这一项为 NULL说明没有使用索引;:key_len 表示索引的长度rows 表示扫描的数据行数。type 表示数据扫描类型。重点 type
All全表扫描index全索引扫描range索引范围扫描ref非唯一索引扫描eq_ref唯一索引扫描const主键或者唯一索引扫描
24、MySQL主从复制了解吗具体复制过程是什么?
MySQL主从复制依赖于binlog复制的过程就是将binlog中的数据从主库传输到从库中去。 具体详细复制过程
MySQL 主库在收到客户端提交事务的请求之后先写入 binlog再提交事务更新存储引擎中的数据事务提交完成后返回给客户端“操作成功“的响应。从库会创建一个专门的 I/0 线程连接主库的 log dump 线程来接收主库的 binog 日志再把 binlog 信息写入 relay log 的中继日志里再返回给主库”复制成功“的响应。从库会创建一个用于回放 binlog 的线程去读 relay log 中继日志然后回放 binlog 更新存储引擎中的数据最终实现主从的数据一致性。