【计算机面试整理2】学习中可能没学到的知识点{面试问题}

ACID,补充了ACID的级别关系

ACID 特性

原子性(Atomicity):
    定义:一个事务中的所有操作要么全部成功,要么全部失败,不能只完成其中一部分。事务被视为一个不可分割的单元。
    示例:在银行转账操作中,转账金额从一个账户扣除并存入另一个账户必须同时完成。如果其中一个操作失败,则两个操作都不应执行。

一致性(Consistency):
    定义:事务执行前后,数据库的状态必须保持一致,即数据库从一个一致性状态变到另一个一致性状态。所有数据库规则(如约束、触发器)必须得到遵守。
    示例:在转账操作中,账户余额总和必须在转账前后保持不变。

隔离性(Isolation):
    定义:多个事务并发执行时,每个事务的执行不应受其他事务的影响。事务之间的操作应互相隔离,确保事务的中间状态不会对其他事务可见。
    示例:两个并发的转账操作不能导致数据不一致,例如一个事务在另一个事务更新余额之前读取余额。

持久性(Durability):
    定义:一旦事务提交,其对数据库的更改应该永久保存,即使系统崩溃或出现故障也不会丢失。
    示例:在转账操作成功提交后,数据库应持久保存该操作的结果,即使系统崩溃,数据也不会丢失。

事务的隔离级别

隔离性是 ACID 特性中的一个关键方面,它定义了多个事务并发执行时,如何隔离事务之间的相互影响。SQL 标准定义了四种隔离级别,按从最低到最高的隔离性进行排序:

读未提交(Read Uncommitted):
    特性:允许一个事务读取另一个事务未提交的数据(脏读)。这是隔离性最差的级别。
    问题:可能会出现脏读、不可重复读和幻读。
    适用场景:对一致性要求不高的场景,但性能最好。

读已提交(Read Committed):
    特性:一个事务只能读取已提交事务的数据。可以避免脏读,但仍然可能出现不可重复读。
    问题:可能会出现不可重复读和幻读。
    适用场景:一般用于大多数业务场景,保证数据的稳定性,性能适中。

可重复读(Repeatable Read):
    特性:确保在一个事务中多次读取同一数据的结果是一致的,避免了脏读和不可重复读。使用幻读的控制机制通常是多版本控制(MVCC)。
    问题:仍然可能出现幻读。
    适用场景:对数据一致性要求较高的场景,例如金融业务。

串行化(Serializable):
    特性:最强的隔离级别,确保事务串行执行(即一个事务完全执行完毕后另一个事务才开始),避免了脏读、不可重复读和幻读。通常通过加锁机制实现。
    问题:性能较差,因为事务被串行化执行,可能导致较低的并发性。
    适用场景:对数据一致性要求极高的场景,如库存管理系统。

进程和线程的区别

功能:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位。

开销:每个进程都有独立的内存空间,存放代码和数据段等,程序之间的切换会有较大的开销;线程可以看做轻量级的进程,共享内存空间,每个线程都有自己独立的运行栈和程序计数器,线程之间切换的开销小。

运行环境:在操作系统中能同时运行多个进程;而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)

创建过程:在创建新进程的时候,会将父进程的所有五大数据结构复制新的,形成自己新的内存空间数据,而在创建新线程的时候,则是引用进程的五大数据结构数据,但是线程会有自己的私有数据、栈空间。进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.

进程和线程其实在cpu看来都是task_struct结构的一个封装,执行不同task即可,而且在cpu看来就是在执行这些task时候遵循对应的调度策略以及上下文资源切换定义,包括寄存器地址切换,内核栈切换。所以对于cpu而言,进程和线程是没有区别的。

Mysql问题

统计一个班级学生每科课程分数都在80分以上的学生名

namecourse_idscore
AliceMath85
AliceEnglish78
AliceScience90
BobMath92
BobEnglish88
BobScience95
CharlieMath80
CharlieEnglish85
CharlieScience83
DavidMath75
DavidEnglish95
DavidScience80
查询语句:
select name
from student
Group by name
having Min(score) >= 80;

输出结果:

name
Bob
Charlie

StringBuilder和StringBuffer的区别

String数组

String在Java中是一个引用类型,其使用时是以对象的形式存在,String对象在进行重新赋值或值发生改变时都是生成一个新的对象。String是使用char数组来存储数据,并且是使用final修饰的,所以String的值一经定义是不可变的。
在这里插入图片描述
JDK9及之后:
在这里插入图片描述

假设String a = “test”+“001” 这时其在堆内存中的占用就是三个部分:
“test”、“001”、“test001”。而a对象的栈内存存储的是"test001"的堆内存地址,这时**"test"和"001"只能等垃圾回收机制进行自动化回收才可以释放。**

我们每次对String的操作都会在内存中产生一个新的String对象,这样不仅效率低而且占用内存空间。
为了解决这个为题,java为我们提供了StringBuffer,在JDK5之后又提供了StringBuilde

StringBuilder

在这里插入图片描述
在new StringBuilder时如果没有传参,则调用父类方法构造一个其中没有字符且初始容量为 16 个字符的字符串构建器。但最终都是调用父类中的方法。

在父类中,使用char数组来存储数据,与String不同的是,没有使用final修饰。

StringBuffer

通常应优先使用StringBuilder类,因为它支持所有相同的操作,但速度更快,因为它不执行同步。
构造方法也与StringBuilder相同。

线程安全原因

StringBuilder与StringBuffer不同的是,StringBuffer的方法使用了synchronized修饰保证线程安全。

StringBuilder和StringBuffer

类型不可变字符串可变字符串线程安全效率
String--
StringBuilder
StringBuffer

都是可变序列
主要操作都是append和insert

StringBuffer是线程安全的,StringBuilder是线程不安全的。同样的StringBuffer在确保线程安全的过程中,牺牲了一定的性能,因此StringBuilder速度是最快的。而两者与String相比其修改过程中是直接作用于指定的堆内存中,通常不会再进行开辟新的堆内存,因此相比String效率更高。因此我们可以得出如下结论:
String < StringBuffer < StringBuilder

Mysql数据库的引擎

Mysql数据库引擎就是管理数据的也可以优化数据的一个软件模块,这个模块可以决定存储,索引,更新,以及删除数据还可以影响的数据库的性能,安全和稳定性,Mysql数据库引擎中包含了很多的类型如在Mysql中就有: InnoDB、MyISAM、Memory、Merge、Archive、CSV、BLACKHOLE等等。

查询存储引擎:

show engines;

以下数据库存储引擎:

EngineSupportCommentTransactionsXASavepoints
InnoDBDEFAULTSupports transactions, row-level locking, and foreign keysYESYESYES
MRG_MYISAMYESCollection of identical MyISAM tablesNONONO
MEMORYYESHash based, stored in memory, useful for temporary tablesNONONO
BLACKHOLEYES/dev/null storage engine (anything you write to it disappears)NONONO
MyISAMYESMyISAM storage engineNONONO
CSVYESCSV storage engineNONONO
ARCHIVEYESArchive storage engineNONONO
PERFORMANCE_SCHEMAYESPerformance SchemaNONONO
FEDERATEDNOFederated MySQL storage engineNULLNULLNULL

InnoDB

使用场景:一般事务性,均使用该引擎,用途最广,如果把握不准使用何种引擎,就使用该引擎。

特点:

使用表级锁;
支持事务。
存储限制:64TG
事务支持:支持ACID事务
适用于需要高可靠性、事务支持、多用户并发的应用,如金融系统、电商网站等。
在MySQL数据库系统中,默认存储引擎是InnoDB,因此它是使用MySQL数据库的重要部分。

ACID事务

原子性(Atomicity):事务是一个原子性质的操作单元,事务里面的对数据库的操作要么都执行,要么都不执行。

一致性(Consistency):在事务开始之前和完成之后,数据都必须保持一致状态,必须保证数据库的完整性。也就是说,数据必须符合数据库的规则。

隔离性(Isolation):一个事务的执行不能被其他事务干扰。即一个事务的内部操作及使用的数据对其他并发事务是隔离的,并发执行的各个事务之间不能互相干扰。

持久性(Durability):持久性也成为永久性,指一个事务一旦提交,它对数据库中数据的改变就应该是永久的。

4种隔离级别

1.读未提交 (Read Uncommitted) :在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)

2.读已提交(Read Committed):这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别也支持所谓的不可重复读(NonrepeatableRead),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果

3.可重复读(Repeatable Read):这是MySQL的默认事务隔离级别,同一事务的多个实例在并发读取数据时,会看到同样的数据。不过理论上,这会导致另一个棘手的问题:幻读(Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。

4.可串行化(Serializable):这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

什么是脏读,幻读,不可重复读?

1.脏读 :

脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
一个事务可以读取到另一个事务尚未提交的数据,这可能导致不一致的结果或不正确的操作。
2.不可重复读 :

是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。如果只有在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题。
同一个事务在不同时间读取同一数据时得到的数据结果不同。
3.幻读:

是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。 同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象 发生了幻觉一样。
同一事务在不同时间执行相同查询时,结果集发生变化(即数据项的数量发生变化)。

MyISAM

特点:

所有的数据都保存在内存中,一旦服务器重启,所有memory存储引擎的表数据会消失但是表结构会保存下来;

数据读取,速度过程较快且占用资源相对少,访问速度快;

表级锁定形式,数据更新时锁整表 。

表级锁是一种用于控制对整个表的并发访问的锁机制
数据库在读写过程中相互阻塞,串行操作,按照顺序操作,每次读写锁全表
会在数据写入的过程阻塞用户数据的读取
也会在数据读取的过程中阻塞用户的数据写入

存储限制:取决于RAM (随机存储器)

支持全文索引

MyISAM 支持全文索引(Full-text indexing),这在处理大量文本数据或执行全文搜索时非常有用。可以在 MyISAM 表上建立全文索引来提高搜索效率。

事务支持:不支持事务

MyISAM 不支持事务处理(Transactions),这意味着它不提供原子性、隔离性、持久性和持久性事务特性。如果在操作过程中发生错误,MyISAM 无法回滚到之前的状态。

存储结构

MyISAM 将表的数据存储在三个文件中:
    .frm 文件:存储表的结构定义。
    .MYD 文件:存储数据。
    .MYI 文件:存储索引。
这种结构使得 MyISAM 表的备份和恢复相对简单,可以通过直接复制这些文件来实现。

MyISAM 存储引擎适用于读操作频繁、对数据一致性要求不高、数据恢复能力要求不高的场景。

Archive

1.使用场景:在日志和数据采集的时候可以使用
2.特点:
只允许插入和查询,不允许修改和删除,压缩存储,节约空间,可以实现高并发的插入,支持在自增ID上建立索引。ARCHIVE存储引擎用于存储大量历史数据,它对数据的压缩率很高,但只支持INSERT和SELECT操作,不支持UPDATE和DELETE。ARCHIVE引擎适用于需要长期保存历史数据但不经常修改的应用。

rarchive表比MylSAM表要小大约75%,比支持事务处理的InnoDB表小大约83%

不支持索引 (自增ID列除外)

MEMORY(HEAP)

MEMORY存储引擎将表数据存储在内存中,因此访问速度非常快。但是,由于数据存储在内存中,一旦MySQL服务器重启,数据就会丢失。MEMORY引擎适用于需要快速临时存储数据的情况,如缓存表。

CSV

CSV存储引擎用于存储CSV格式的数据文件,支持读写CSV文件,但不支持索引和事务处理。它适用于需要导入或导出CSV格式数据的应用。

BLACKHOLE

BLACKHOLE存储引擎接收数据但不将其存储,它通常用于复制数据到其他MySQL服务器。

FEDERATED

FEDERATED存储引擎用于在多个MySQL服务器之间建立联合表,允许在不同服务器上查询和操作数据。

NDB Cluster(NDB)

NDB Cluster存储引擎用于MySQL集群(MySQL Cluster),它提供了高可用性和分布式存储功能,适用于需要实时数据复制和故障切换的应用。

测试用例的设计方法

在这里插入图片描述

定义:

是为了特定的目的而设计的一组有测试输入、执行条件、预期结果的案例(文档)。
在这里插入图片描述

构成要素

在这里插入图片描述
样例:

在这里插入图片描述

设计方法

在这里插入图片描述

1.测试设计方法—等价类划分

概念:在所有测试的数据中,具有某种共同特征的数据子集。

在这里插入图片描述

等价类划分规则:

在这里插入图片描述#### 等价类设计测试用例的步骤:

在这里插入图片描述

2.边界值分析法

定义:

在这里插入图片描述

边界值的上点离点内点:

在这里插入图片描述

步骤:

在这里插入图片描述

对于开区间(),上点是无效数据,离点是有效数据
对于闭区间[],上点是有效数据,离点是无效数据

3.判定表法

在这里插入图片描述
等价类方法无法覆盖:不欠费不停机 允许主被叫

规则:

在这里插入图片描述

步骤:

在这里插入图片描述

因果图法

在这里插入图片描述在这里插入图片描述

步骤(案例)()

状态迁移图法

在这里插入图片描述

案例:

在这里插入图片描述

场景法

在这里插入图片描述

步骤

在这里插入图片描述

案例

在这里插入图片描述

正交实验法

在这里插入图片描述

步骤

在这里插入图片描述

错误推测法

在这里插入图片描述

黑盒测试用例设计方法总结

在这里插入图片描述

Hashmap的底层数据结构和原理

原文链接
HashMap 就是以 Key-Value 的方式进行数据存储的一种数据结构嘛,在我们平常开发中非常常用,它在 JDK 1.7 和 JDK 1.8 中底层数据结构是有些不一样的。总体来说,JDK 1.7 中 HashMap 的底层数据结构是数组 + 链表,使用 Entry 类存储 Key 和 Value;JDK 1.8 中 HashMap 的底层数据结构是数组 + 链表/红黑树,使用 Node 类存储 Key 和 Value。当然,这里的 Entry 和 Node 并没有什么不同,Node 类的源码如:
在这里插入图片描述

例子:put(“小牛肉”,20),我插入了一个 key 为 “小牛肉” value 为 20 的元素,这个时候我们会通过哈希函数计算出这个元素将要插入的位置,假设计算出来的结果是 2:在这里插入图片描述
首先,数组的长度是有限的对吧,在有限的数组上使用哈希,那么哈希冲突是不可避免的,很有可能两个元素计算得出的 index 是相同的,那么如何解决哈希冲突呢?拉链法。也就是把 hash 后值相同的元素放在同一条链表上。比如说:

在这里插入图片描述

当然这里还有一个问题,那就是当 Hash 冲突严重时,在数组上形成的链表会变的越来越长,由于链表不支持索引,要想在链表中找一个元素就需要遍历一遍链表,那显然效率是比较低的。为此,JDK 1.8 引入了红黑树,当链表的长度大于 8 的时候就会转换为红黑树,不过,在转换之前,会先去查看 table 数组的长度是否大于 64,如果数组的长度小于 64,那么 HashMap 会优先选择对数组进行扩容 resize,而不是把链表转换成红黑树。
在这里插入图片描述
JDK1.8下的Hashmap数据结构:
在这里插入图片描述

新的 Entry/Node 节点在插入链表的时候,是怎么插入的?

在 JDK 1.7 的时候,采用的是头插法,看下图:
在这里插入图片描述

不过 JDK 1.8 改成了尾插法,这是为什么呢?因为 JDK 1.7 中采用的头插法在多线程环境下可能会造成循环链表问题。

首先,我们之前提到,数组容量是有限的,如果数据多次插入并到达一定的数量就会进行数组扩容,也就是resize 方法。什么时候会进行 resize 呢?与两个因素有关:

1)Capacity:HashMap 当前最大容量/长度

2)LoadFactor:负载因子,默认值0.75f

==和equal的区别

== 为运算符,equal 为String数据类型的比较方法;相同内容的对象地址不一定相同,但相相同地址的对象内容一定相同;

== 比较的是值是否相等,equal比较的是是否是同一个对象。

==

对于==,比较的是值是否相等:

如果作用于基本数据类型的变量,则直接比较其存储的 值是否相等,
如果作用于引用类型的变量,则比较的是所指向的对象的地址是否相等。

equals方法

对于equals方法,比较的是是否是同一个对象:

首先,equals()方法不能作用于基本数据类型的变量,
另外,equals()方法存在于Object类中,而Object类是所有类的直接或间接父类,所以说所有类中的equals()方法都继承自Object类,在没有重写equals()方法的类中,调用equals()方法其实和使用==的效果一样,也是比较的是引用类型的变量所指向的对象的地址
不过,Java提供的类中,有些类都重写了equals()方法,重写后的equals()方法一般都是比较两个对象的值,比如String类。

两者区别:

== 为运算符 equal 为String数据类型的比较方法.equal()两者的比较范围一方面是基础数据类型(例如 int a = 1),== 与 equal 都是作用于比较对象内容(堆)是否相同。另一方面则是引用对象类型(例如 int a = new int(1)), == 与 equal 都是作用于比较对象内存地址(栈)是否相同。

1、功能不同。'=='是判断两个变量或实例是不是指向同一个内存空间。'equals’是判断两个变量或实例所指向的内存空间的值是不是相同。

2、定义不同。‘equals’在JAVA中是一个方法。’=='在JAVA中只是一个运算符合。

3、运行速度不同。‘equals’比’=='运行速度要慢。

StringBuffer类中没有重新定义equals这个方法,因此这个方法就来自Object类,而Object类中的equals方法是用来比较“地址”的。

算法题

输入一个字符串计算最大无重复的字串

场景题

为微信发消息设计测试用例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值