java面试

1.ArrayList 和 LinkList

字面上来看,两个都实现了List接口。

ArraryList是基于索引的数据接口,底层是数组,以O(1)时间复杂度对元素进行随机访问,线程不安全的。LinkList以元素列表的形式存储数据,还会存储指向下一个节点的指针,本质是双向链表,有头尾节点,首尾指针,以O(n)时间复杂度对进行查找元素。

很多插入,添加,删除的操作使用LinkList,因为当元素被添加到集合的任意位置的时候,改变指针方向就行,不需要项数组一样重新计算大小或者跟新数组。缺点是更占内存。  

很多查询的时候,选择ArrayList。

2.JDK  包含 JRE  包含 JVM(JDK>JRE>JVM)

JDK:java标准开发包,提供了编译运行java程序所需的工具和资源。如果单写java程序,用txt就可以了,那么要运行java程序就需要JDK。

JRE(java运行环境) 和JVM(java虚拟机)都是运行java的字节码文件,JVM是JRE的一部分。比如*.class文件就需要JRE了。

jvm就是一个翻译工作,动态的将java代码翻译成操作系统能识别的机器码。

字节码是什么 和好处

字节码就是生成虚拟机能够理解的代码,扩展名为.class的文件,因为每一种平台的解释器不同,但是实现的虚拟机是相同的。所以不仅解决了传统解释型语言执行效率低的问题,还保留的可移值的特点,不需要重新编译便可以在多种不同的计算机上运行。

3.HashCode()和equals()之间的关系(字符串能不能修改的问题)

在比较两个对象是否相等时,会先调用对象的HashCode()方法得到HashCode进行比较,一样在通过equals()方法确定两个对象是否相等。

4.String StingBuffer StringBuilder 区别

String是不可变的,如果要去修改,会新生成一个字符串对象,另外两个是可变的。append方法

StingBuffer是线程安全的,StringBuilde是线程不安全的,所以单线程环境StringBuilde效率更高。

5.== 和equals方法

 基本数据类型

 

整数型:byte、short、int、long
浮点型:float、double
字符型: char
布尔型: boolean

除了8中基本数据类型以外都是引用数据类型,引用数据类型分3种:类,接口,数组;

final 以及匿名内部类和局部内部类只能访问局部final变量

修饰变量且要给个初始化。

 

 内部类和外部类是同一级别,内部类不会因为定义在方法中就会随着方法的执行完毕就被销毁。那么外部类方法结束时,局部变量被销毁了,但内部类对象可能还存在,怎么访问这个局部变量呢,其实我们是将局部变量复制为内部的成员变量,那么为了防止变量不一致,所以我们才只能使用final去修饰变量。

 6.List 和Set 的区别

 7HashMap 和HashTable 和底层实现

数组和链表都是存储节点数据上的。

 8.1.7和1.8的HashMap的变化(底层)

9.ConcurrentHashMap原理 (7.是entry对象,8是node对象)

cas就是保持原子性

10.深拷贝和浅拷贝 

 

 

 浅拷贝只复制引用地址,不会拷贝到引用地址指引的对象,因此操作出来是同一个对象。而深拷贝连对象也会拷贝出来,是两个对象了。

 

11.CopyOnWriteArrayList 的原理

 

意思就是在添加数据时,写操作会在新数组操作,读操作会在旧数组操作,就不会发生堵塞状态。

 

12.java中的异常体系

 

 异常如果能自己处理就捕获异常,不能就抛出异常给上层处理。

13.java的类加载器,以及类加载器双亲委派模型

 

 Java中的类加载机制是指在Java程序运行时,将类的字节码加载到内存中并转化为可执行的结构的过程。类加载器负责从文件系统、网络或其他来源加载类文件,并生成对应的Class对象。

Java类加载机制遵循以下三个重要原则:

  1. 类的延迟加载:在Java中,类只有在首次被使用时才会进行加载。这种延迟加载的策略可以提高程序的启动性能和内存的利用效率。

  2. 双亲委派模型:Java类加载器采用了双亲委派模型。当一个类加载器需要加载某个类时,它首先会委派给其父类加载器去尝试加载。只有在父加载器找不到该类时,才由子加载器自己尝试加载。通过这种层级关系,可以确保类的一致性和安全性。

  3. 缓存机制:类加载器在加载类后,会将生成的Class对象缓存在JVM的方法区中,以便下次使用时直接获取。这样可以避免重复加载相同的类,提高运行效率。

 类加载机制在Java中起着重要的作用,它为Java程序提供了动态性和灵活性。通过自定义类加载器,可以实现热部署、动态加载等功能,使得Java程序更具扩展性和适应性。

14.Java判断对象是否可回收

 

 

 GC root对象

 如何回收垃圾

标记清除法:从gcroot出发,标记gc可达的对象,没标记的清除。

复制算法:将原有的内存空间分为两部分,只使用一块部分,把正在使用的内存空间存活的对象复制到另一部分,原来部分的全部清除。

标记压缩法:从gcroot出发,将存活的对象压缩在一边,然后在清理边界外的空间。

15.如何排除JVM的问题,或者查看内存溢出的命令

或者查看内存溢出的命令

 

 16 哪些是JVM的共享区

 

 

 方法区:储存类的信息。 堆:储存类所产生的各个对象。  虚拟机栈:某个线程执行的方法。 程序计算器:判断执行哪行代码。

16.线程安全的理解

 

 

 设置守护线程:thread.serDaemon(true)       GC垃圾回收线程就是一个经典的守护线程。

 

 17.ThreadLocal的底层原理比如应用在MP技术的公共字段自动填充时存入value,因为当客户端发送HTTP请求时,对应的服务端都会分配一个新的线程来处理。那么就能取到同一个线程的value值了

 

 

 

ThreadLocal内存泄漏以及如何避免

 

 

 避免

 

 

18.串行、并行、并发

 

 19.如何避免死锁

首先打开idea控制台,使用jps查看进程编号,jstack 进程号,查看控制台输出

 

20.线程池的底层原理和先添加队列再添加线程

队列加线程实现的。执行任务时 corePoolSize -> workQueue->maximumPoolSize->keepliveTime

 

 

 21ReentrantLock的公平锁和非公平锁

 

 

22 ReentrantLock的tryLock()和lock()方法

 

 就是阻塞不阻塞的区别,lock()成功就继续,没成功一直阻塞。

 

23.CountDownLatch 和Semaphore的区别和原理

 

 

 24.Syschronized和ReentranLock(都是同步锁)

AbstractQueuedSynchronizer(AQS)

25

getBean()里面是同一名字就是单例模式,不是同一名字只是单例Bean,可以new很多不同名字的Bean.

 26.spring是什么

整合技术,形成框架

控制反转IOC(Inversion of Control:控制的是对象的创建过程,反转的是创建对象的主体由程序员转化为容器。在spring中容器就是一个单例工厂,每一个对象称为bean,我们只需要在外部定义一个bean的构建过程,而真正的创建由容器来负责。

AOP:将不同的类不同的方法中的共同处理抽取成一个切面。

 27  先通过component-scan扫描路径,解析类

 spring容器启动就是扫描所有的Beanfinition,通过构造方法实例化对象,在依赖注入,再回调,再初始化,再用。对Bean的操作,以及处理一些注解。

 28 BeanFactory和ApplicationContext的区别

 

 

 

29spring的单列Bean是线程不安全的。因为spring并没有对Bean做线程安全处理

还得看你这个Bean对象的各种·方法和各种属性,有没有用sychonazi呀,有没有用锁呀。如果Bean里面有些方法去修改属性,那么就是有状态的,因为Bean是共享的,所以多个线程去修改就会导致线程不安全。

30spring事务的实现方式

用了注解相当于把数据库的自动提交给false了

 

31事务传播机制,就是@Transaction的参数

就像事务a和事务b 如果两个都有事务,如果a回滚,b要不要回滚,b要回滚,a要不要回滚。

比如REQUIRED(required)spring默认的,如果a没事务,则b新建一个事务,有则加入。SUPPORTS(supports):当前存在事务就加入,没有就以非事务方法执行

NEVER(never):不使用事务,如果a有事务,b就报异常。还有别的事务参数。

 

32spring事务什么时候会失效

spring事务的原理是AOP,进行了切面增强,失效原因是Aop不起作用

比如1.方法不是public,@Transactional只能用在public的方法上,实在要非public就开启Adpectj代理模式。

2.数据库不支持事务管理,比如MyIsam.,比如分库的时候,一个要查有事务的库,一个查没有事务,那么注解也会失效。3.没有被spring管理。4.异常被吃掉,事务不会回滚。

 

32.spring springmvc springboot

spring是一个IOC容器,有两个关键点,依赖注入和控制反转,通过依赖注入实现控制反转,方便整合各种框架,提高AOP机制弥补OOP的代码重复问题,方便将不同的类不同的方法中的共同处理抽取成一个切面,自动注入给方法执行。

依赖注入的核心思想是将对象之间的依赖关系交由容器来管理,而不是由对象自身负责创建或查找依赖的对象。通过依赖注入,对象可以从容器中获取它所需要的依赖,并且无需关心依赖对象的具体实现和创建过程。

控制反转是指将对象的创建、管理和依赖的控制权从应用程序代码中转移到外部容器(例如Spring容器)中。依赖注入实现控制反转

springmvc 是spring对web框架的一个解决方案,提供一个总的前端控制器Servlet,用来接收请求,然后定义一套路由策略,和执行handle,将结果使用视图解析来生成视图给前端。

springboot:是一个快速的开发工具包,使程序员更快开发spring+springmvc的应用,通过加入坐标以及配置整合技术,比如redis,mybatis等等,而且实现了很多统一接口,只要更改实现方式就能更改技术,比如缓存技术,开箱即用。

 微服务

微服务(Microservices)是一种软件开发架构风格,将应用程序拆分为一组小型、独立的服务单元,每个服务单元都有自己独立的进程和数据存储,通过轻量级的通信机制互相协作。每个服务单元可以被独立开发、测试、部署和扩展,使得整个系统更容易理解、开发和维护。

springcloud

Spring Cloud是一个基于Spring Boot的开发工具箱,它提供了一系列用于快速构建分布式系统的组件和功能。Spring Cloud简化了分布式系统的开发复杂性,通过提供配置管理、服务注册与发现、负载均衡、断路器、消息总线、分布式追踪等功能,使得开发人员可以更轻松地构建可靠、弹性和可扩展的分布式应用程序。

下面是Spring Cloud的几个核心组件和功能:

  1. 服务注册与发现:Spring Cloud提供了服务注册与发现的功能,使得各个微服务实例可以自动注册到服务注册中心,并能够通过服务名进行访问与调用。常用的服务注册与发现组件包括Netflix Eureka和Consul。

  2. 负载均衡:Spring Cloud集成了负载均衡功能,可以根据一定的策略将请求分发到多个服务实例上,以达到负载均衡和高可用的目的。常用的负载均衡组件包括Netflix Ribbon。

  3. 配置管理:Spring Cloud提供了集中化的配置管理功能,可以将应用程序的配置信息集中存储在配置中心,并在运行时动态获取。常用的配置中心组件包括Spring Cloud Config和Consul。

  4. 断路器:Spring Cloud集成了断路器模式,可以在微服务之间进行故障保护和容错处理。当某个微服务出现故障或过载时,断路器可以快速失败并返回预定的响应,避免级联故障。常用的断路器组件包括Netflix Hystrix。

  5. 分布式追踪:Spring Cloud通过集成Zipkin和Sleuth等组件,提供了分布式追踪的功能,可以跟踪请求在分布式系统中的调用链路和性能指标,帮助开发人员排查和解决问题。

  6. 消息总线:Spring Cloud提供了消息总线功能,可以方便地进行应用程序之间的消息传递和广播。常用的消息总线组件包括Spring Cloud Bus和Kafka。

除了以上功能外,Spring Cloud还提供了其他一些有用的组件和工具,如服务网关(Zuul、Spring Cloud Gateway)、分布式事务(Spring Cloud Alibaba)、批处理(Spring Cloud Task)等。

通过使用Spring Cloud,开发人员可以更加轻松地构建和管理分布式系统,减少了开发的复杂性,并提供了一致性、可靠性和弹性等特性。同时,Spring Cloud还与Spring生态系统紧密集成,可以很好地与Spring Boot应用程序无缝集成,简化了开发和部署流程,提高了开发效率。

33.什么是Bean的自动装配

开启自动装配,只需要xml配置文件中<bean>中定义“autowire”属性,比如缺省情况下,自动装配通过“ref”属性手动设定,autowire的参数可以填byName,byType,constructor构造方法等

还有一个就是自动装配@Autowire

34 mybatis的优缺点

sql语句写在xml文件里,解除了sql程序代码的耦合,便于统一管理。与JDBC相比减少50%的代码量,最大直观就是不用手动开关连接,很好的与数据库兼容,对spring很友好,友好集成,提供映射标签。

缺点嘛其实我认为是对sql的编写考验程序员对sql的功底,然后数据库移植性差,比如移动到oracle,对sql要重新编写。

 什么是mybatis

MyBatis是一个开源的Java持久层框架,可以通过简单的配置文件完成数据库操作,将数据库操作抽象为映射文件(Mapper XML)中的SQL语句

35

 36.

37

 

 38

 

 

 

 多线程:如果一个业务逻辑很复杂,每一个请求都要很长时间就要用到多线程,因为用单线程会阻塞,在Redis中,都是对key进行简单的操作,操作是很快的所以用单线程。

3)就是cpu在线程的切换问题。

单双线程:

 通过查看系统的CPU使用情况,如果只有一个核心在运行,则是单线程系统;如果有多个核心在运行,则是多线程系统。

 

 39 缓存雪崩、缓存穿透、缓存击穿 (都会导致所有的请求都落到数据库上,造成数据库短时间承受大量请求而奔溃)

缓存雪崩:指缓存同一时间大面积的失效。解决方案:1)缓存数据的过期时间设置随机。2)互斥锁(当访问数据库里的数据是,给缓存的key加锁,直到取到数据才释放锁)

缓存穿透:缓存和数据库都没有数据。解决方案:将key-value对写成key-null。

缓存击穿:指缓存没有但数据库有数据(一般缓存时间过期)这里指的是并发查同一条数据,缓存雪崩是不同数据都过期。解决方案:设置热点数据永远不过期。2)互斥锁

40.RabbitMQ

大致流程 :生产者发消息,我们指定RoutingKey给Exchange,由Exchange将RoutingKey与绑定键Binding去匹配(两者结合叫路由规则),再放入Queue中。

direct模式就要求路由规则完全匹配。一对一,绝对匹配

topic模式,一对多,RountingKey对多个Binding,可以模糊匹配

Fanout交换机则会忽略RoutingKey。

TCP连接就像电缆,信道就是光纤。(TCP连接就是网卡主动从缓冲区拷贝数据,缓冲区的数据是我们不直接向网卡驱动发数据,而是先放入一个缓冲区)

 

 

 41能否确认发送到Queue和消费者接收

 

第一个问题(生产者在等待确认的同时,可以继续发送消息,异步的)

信道需要设置为confirm模式,则所有信道发送发布的消息都会分配一个唯一ID,一旦消息被投递到queue(可持久化的消息需要写入磁盘),信道发送一个确认给生产者,通过过回调接口ConfirmCallback接口(包含消息唯一ID) ack

没有到Queue就发送ReturnCallback,表示消息失败 nack

 

 第二个问题(消费者就不是通过信道了 noAck默认为true)

没确认,RabbitMQ不会投递下一条消息给同一个消费者,确保不是断开链接或者超时,起到限流的作用,不做无用功。而是确保数据最终一致性

 

 

 去重,比如第一次接收ID存入数据库或者redis中,下一次再接收到这个ID,已经消费了则把返回ack给RabbitMQ去删除消息即可

43RabbitMQ事务消息

对信道设置了事务模式,则发送消息不会马上到Queue,而是发送到一个临时队列中,只有提交事务了才会放入真正的Queue。(前提是autoAck = false)

 

 44.

消息没到Queue(nack)或者超过TTL时间或者事务回滚都会到死信队列。

 

 

 45.抽象类和接口的区别

1.抽象类要被子类继承,接口要被类实现。

2.接口只能做方法声明,抽象类中可以作方法声明,也可以做方法实现。

3.接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。

jdk1.8之后在接口 中加入default有个默认块、和static都可以实现方法

 

46反射

Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。反射机制允许程序在运行时取得任何一个已知名称的class的内部信息 。通过 Class 类获取成员变量、成员方法、接口、超类、构造方法等。

getName():获得类的完整名字。
getFields():获得类的public类型的属性。getMethods():获得类的public类型的方法。

 

47注解失效的场景

如果Transactional注解应用在非public修饰的方法上,Transactional将会失效。

48为什么都用 List list = new ArrayList();

50post和get

POST和GET是HTTP协议中两种常见的请求方法,它们在以下方面有所不同:
1.参数传递方式:
GET:通过URL的查询字符串(query string)传递参数,参数会附加在URL的末尾,例如http://example.com/path?param1=value1&param2=value2。
POST:通过请求体(request body)传递参数,参数不会直接显示在URL中。
2.数据传输方式:
GET:使用URL进行数据传输,数据量较小,一般限制在几千个字符以内。
POST:使用请求体进行数据传输,没有对数据量大小的限制,可以传输大量数据。
3.安全性:
GET:由于参数暴露在URL中,容易被截获,相对不安全。因此,不应该用于传输敏感信息,例如密码等。
POST:参数在请求体中,相对安全,但并不代表绝对安全。适合用于传输敏感信息和大量数据。
4.缓存:
GET:请求可被缓存,可以被浏览器缓存或代理服务器缓存。
POST:默认情况下不可被缓存,每次请求都需要服务器处理。
总结起来,GET适合用于获取资源、查询数据,对缓存友好;POST适合用于发送数据、提交表单,能处理大量数据和敏感信息。

 51标识符规范

 52序列化和反序列化

序列化:把对象转化为字节序列的过程。反序列化:把字节序列恢复为对象的过程。

什么时候需要呢?当我们将内存的对现象持久化到磁盘,数据库中,或者需要与浏览器进行交互时就需要序列化和反序列化了。

53.String类不可变的原因

如果一个对象在创建后不能改变它的状态,那么这个对象就是不可变的。不能改变状态的意思是不能改变对象内的成员变量,包括基本数据类型的值不能改变,引用类型的变量不能指向其他的对象,引用类型指向的对象的状态也不能改变。源码中部分的主要由两个字段value和hash从源码可以看出string对象其实在内部就是一个个字符,存储在这个value数组里面的,value数组用final修饰了。且字段都是私有的。

 54.String为什么要设计成不可变的

1.线程安全:同一个字符串实例可以被多个线程共享,因为字符串不可变,本身就是线程安全的。

2.安全考虑:像url,密码,path通常情况都是以String类型保存,要是String可变将会引起隐患。

55bin log和redo log的区别

1.bin log会记录所有日志记录,包括InnoDB和MyISAM等存储引擎的日志,redo log只记录innoDB自身的事务日志。

2.bin log是逻辑日志,记录sql语句的原始逻辑。redo log是物理日志,记录某个数据页做了什么修改。

3.bin log只是事务提交前写入到磁盘,一个事务只写一次。在事务进行过程会有redo log不断写入磁盘。

多线程

Java多线程是指在Java程序中同时执行多个线程的机制。多线程可以让程序同时执行多个任务,提高程序的并发性和效率。

多线程怎么保证代码的有序性

通过 synchronized 关键字、Lock 对象或者使用并发容器中的线程安全集合来实现线程间的同步。volatile 关键字,确保多个线程对该变量的读写操作是有序的。

 56在Java中,有多种方式可以创建线程:

继承Thread类:创建一个继承自Thread类的子类,并重写其run()方法来定义线程的执行逻辑。然后通过创建该子类的实例,调用start()方法启动线程。示例代码如下:
public class MyThread extends Thread {
@Override
public void run() {
// 线程执行的逻辑
}
}
// 创建并启动线程
MyThread myThread = new MyThread();
myThread.start();

实现Runnable接口:创建一个实现了Runnable接口的类,并实现其run()方法作为线程执行的逻辑。然后通过创建该类的实例,将其作为参数传递给Thread类的构造函数,再调用start()方法启动线程。示例代码如下:
public class MyRunnable implements Runnable {
@Override
public void run() {
// 线程执行的逻辑
}
}

// 创建并启动线程
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();

使用匿名类或Lambda表达式:基于第二种方式,可以使用匿名类或Lambda表达式来简化代码,如下所示:
// 使用匿名类创建并启动线程
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// 线程执行的逻辑
}
});
thread.start();
// 使用Lambda表达式创建并启动线程
Thread thread = new Thread(() -> {
// 线程执行的逻辑
});
thread.start();
无论使用哪种方式,都可以创建并启动新的线程。然而,除非有特殊需求,推荐使用实现Runnable接口或使用Lambda表达式的方式来创建线程,因为Java中的类可以实现多个接口,而继承Thread类则无法再继承其他类。此外,实现Runnable接口也更符合面向对象的设计原则。

57线程池

线程池(Thread Pool)是一种用于管理和复用线程的机制,它可以减少线程的创建和销毁开销,并提高线程的执行效率。线程池中包含一个线程队列和一组管理线程的机制。

在线程池中,有一个线程队列用于保存需要执行的任务。当有新的任务到达时,线程池会从队列中获取一个空闲线程来执行任务,而不是每次都新建一个线程。当任务执行完成后,线程不会立即销毁,而是返回线程池等待下一次任务。

如何创建线程池

创建线程池实例:
// 创建固定大小的线程池,池中的线程数量为3
ExecutorService executorService = Executors.newFixedThreadPool(3);
在这个示例中,通过Executors工厂类的newFixedThreadPool()方法创建了一个固定大小的线程池,池中最多同时执行3个线程的任务。你也可以使用其他的静态工厂方法来创建不同类型的线程池,如newSingleThreadExecutor()创建只有一个线程的线程池、newCachedThreadPool()创建可根据需要自动扩容的线程池等。

提交任务给线程池执行:
// 提交任务给线程池
executorService.execute(new Runnable() {
@Override
public void run() {
// 任务执行的逻辑
}
});
通过execute()方法将任务提交给线程池执行。可以使用匿名类或Lambda表达式来创建Runnable对象,表示要执行的任务逻辑。

关闭线程池:
// 关闭线程池
executorService.shutdown();
最后,通过调用shutdown()方法来关闭线程池。这会等待已提交的任务执行完成,并防止新任务被接受。如果希望立即停止所有任务并关闭线程池,可以使用shutdownNow()方法。

58通过线程池完成定时任务(毫秒)

使用java.util.concurrent包:
// 创建ScheduledExecutorService实例
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
// 延迟一段时间后执行任务
executorService.schedule(new Runnable() {
@Override
public void run() {
// 定时任务的逻辑
}
}, 10, TimeUnit.SECONDS);

// 延迟一段时间后周期性地执行任务
executorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
// 定时任务的逻辑
}
}, initialDelay, period, TimeUnit.SECONDS);

// 关闭ScheduledExecutorService
executorService.shutdown();
在这个示例中,使用了ScheduledExecutorService类,通过Executors工厂类的newScheduledThreadPool()方法创建了一个具有固定线程数量的调度线程池。然后,可以调用schedule()方法来延迟执行一次的任务,或者调用scheduleAtFixedRate()方法来延迟一段时间后周期性地执行任务。

59两个线程能在cpu中同时进行吗

在单核处理器的情况下,无法真正实现两个线程同时在CPU中执行。单核处理器只能在同一时间点执行一个指令,因此在任何给定的时刻只有一个线程可以在CPU中执行。

然而,在多核处理器系统中,不同的线程可以在不同的核心上同时执行。每个核心都有自己的执行单元和缓存,可以独立执行指令。这样,多个线程可以并行地在多个核心上执行,从而实现在CPU中同时进行。

需要注意的是,并行执行的线程之间可能会涉及到竞争条件和资源共享的问题。在设计多线程应用程序时,需要采取适当的同步机制(如锁、信号量等)来确保对共享资源的访问是安全的,以避免数据不一致或死锁的问题。

60.Java类成员的访问控制权限:

public > protected > 同包(default) > private

61间隙锁(Gap Lock)和多版本并发控制(MVCC)是数据库中两种常见的并发控制机制,数据库的高并发:

1.间隙锁(Gap Lock):

使用情况:间隙锁通常在事务中进行范围查询或范围锁定时使用。当事务需要对一个范围内的数据进行读取或写入时,可以使用间隙锁来保护这个范围内的数据,防止其他事务在该范围内插入或修改数据。
工作原理:间隙锁是一种特殊类型的锁,在锁定范围内的数据同时会对范围之外的间隙(即不存在的数据)进行锁定。这样做是为了防止其他事务在范围内插入新的数据,从而保证读取或锁定操作的一致性。
2.多版本并发控制(MVCC):

使用情况:MVCC通常用于数据库系统中实现读取一致性和高并发性。它通过在事务开始时创建一个快照(视图)来允许多个事务并发进行读取操作,并且每个事务可以看到自己的快照状态,而不受其他事务修改的影响。
工作原理:在MVCC中,每个数据行都会有多个版本,每个事务读取数据时,会根据自己的快照时间戳,选择符合条件的数据版本进行读取。当有其他事务修改数据时,不会直接影响到已经存在的旧版本,而是创建新的版本,并更新对应的事务快照。

62Java中常用的设计模式有以下几种:

单例模式(Singleton Pattern):确保一个类只有一个实例,并提供全局访问点。
工厂模式(Factory Pattern):创建对象的过程封装到工厂类中,通过工厂来创建对象。
原型模式(Prototype Pattern):通过克隆已有对象来创建新对象,避免了重复创建相似对象的过程。
建造者模式(Builder Pattern):将一个复杂对象的构建过程与其表示分离,使同样的构建过程可以创建不同的表示。
桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化,降低两者之间的耦合性。
观察者模式(Observer Pattern):定义了对象间的一对多依赖关系,当一个对象状态发生改变时,其相关依赖对象会收到通知并自动更新。
策略模式(Strategy Pattern):定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。

63.封装、继承、多态

封装(Encapsulation):
封装是一种将数据和操作封装在类中的机制,使得类的内部细节对外部是不可见的,只暴露出必要的接口供其他对象进行交互。封装可以实现信息的隐藏和保护,提高代码的安全性和可维护性。通过定义类的成员变量和成员函数,并使用访问修饰符(如 private、protected、public)来控制其可见性,以达到封装的目的。

继承(Inheritance):
继承是一种通过建立基类(父类)和派生类(子类)之间的关系,实现代码的重用和扩展性的机制。派生类可以继承基类的属性和方法,并且可以添加自己特有的属性和方法,同时还可以覆盖或重写基类中的方法。继承可以提高代码的可维护性和可扩展性,同时也能够体现出类与类之间的关系。

多态(Polymorphism):
多态是指对于同一个消息,不同的对象可以作出不同的响应。多态性主要有两种实现方式:静态多态和动态多态。静态多态是指通过重载(函数名相同,参数个数或类型不同)实现的多态性,编译器在编译时根据调用的方法选择合适的重载函数。动态多态是指通过继承和虚函数(在基类中定义虚函数,在派生类中进行重写)实现的多态性,运行时根据对象的实际类型来调用相应的方法。

64最新的 JDK 版本是 JDK 17。于 2021 年 9 月发布 

1.Sealed Classes (密封类)引入了新的修饰符 sealed,可以限制一个类的子类范围,从而提供更严格的类层次结构。

2.增强了 Switch 表达式的语法,支持更灵活的模式匹配和类型推断。
3.加强了对 JDK 内部 API 的封装,以提高代码的可靠性和安全性。

65redis与数据库数据不一致

光查询是不会发生数据不一致的情况,只有读写一起的时候才会发生。线程1发起修改数据的请求,先把redis的数据删掉再修改数据库的数据此时网络卡顿,线程2并发进来执行的是一个查询请求,会去redis查询数据,因为线程1已经删除了缓存所以查不到就去数据库查,但是线程1网络卡顿数据还没跟新,因此查出来的是老数据并把数据存到redis中,而数据库后变成新数据,因为redis有过期时间,当在没到过期时间其他线程查询的都是老数据。这就是导致数据不一致。

解决方法延时双删:当线程1跟新完数据库的数据后,再删一次缓存。要想线程2也查到新的数据就需要引入强一致性的概念。强一致性就需要加锁保证数据库和redis是原子性操作。

posted @   张福祥  阅读(64)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示