文章目录
提问问题
- 笔试题:给定一个只包括
(,
)
,{
,}
,[,
]
的字符串s
,判断字符串是否有效 - 笔试题:加油站问题;给一个汽油获取和消耗数组gas = [1,2,3,4,5], cost = [3,4,5,1,2],求输入数组是否能找到一个起点能绕数组一圈。
- TCP 的 Keepalive 和 HTTP 的 Keep-Alive 是⼀个东⻄吗?
- TCP连接如何确保可靠性
- 说说拥塞控制是怎么实现的?
- Cookie和Session是什么?有什么区别?
- 解释⼀下进程同步和互斥,以及解决这些问题的⽅法
什么是中断和异常?它们有什么区别?
线程同步的⽅式有哪些?
MySQL的执⾏引擎有哪些?
MySQL⽇志⽂件有哪⼏种?
MySQL有哪些锁?作⽤是什么?
问题1
这种括号匹配肯定是用栈结构; 可以先入右括号,然后只需要比较当前元素和栈顶相不相等就可以了!代码如下;
更详细思路可以参考之前的文章有效括号
class Solution {
public boolean isValid(String s) {
int len= s.length();
if(len%2==1){ return false;}//有效字符串的长度一定为偶数,若为奇数则直接返回false
Map<Character , Character > pairs =new HashMap<Character,Character>(){{
put(')','(');//键为右括号,值为相同类型的左括号
put('}','{');
put(']','[');
}};
Deque<Character> stack=new LinkedList<Character>();
//遇到一个右括号时,将一个相同类型的左括号闭合
for(int i=0;i<len;i++){
char ch=s.charAt(i);//遍历字符串
if(pairs.containsKey(ch)){//碰到右括号时
//栈为空或者没有匹配的左括号 返回false
if(stack.isEmpty() || stack.peek() !=pairs.get(ch)){
return false;
}
stack.pop();//否则闭环
}else { stack.push(ch);}//左括号入栈
}
return stack.isEmpty();//栈若为空说明全部括号都闭合了
}
}
问题2
首先总油量减去总消耗大于等于零那么一定可以跑完一圈,找起点就从头遍历,油减油耗如果有负数就当前遍历点加1,重新计算,直到遍历完总油耗还是大于0,所以代码如下
更详细思路可以参考之前的文章加油站问题
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int curSum = 0;//当前油耗
int totalSum = 0;//全部油耗
int index = 0;//起点
for (int i = 0; i < gas.length; i++) {
curSum += gas[i] - cost[i];
totalSum += gas[i] - cost[i];
if (curSum < 0) {
index = (i + 1) % gas.length ; //更换新起点
curSum = 0;
}
}
if (totalSum < 0) return -1;
return index;
}
}
问题3
Keep-Alive和Keepalive不是一个东西
HTTP 的 Keep-Alive,是由应⽤层(⽤户态) 实现的,称为 HTTP ⻓连接;
每次请求都要经历这样的过程:建⽴ TCP -> 请求资源 -> 响应资源 -> 释放连接,这就是HTTP短连接,但是这样每次建⽴连接都只能请求⼀次资源,所以HTTP 的 Keep-Alive实现了使⽤同⼀个TCP 连接来发送和接收多个 HTTP 请求/应答,避免了连接建⽴和释放的开销,就就是 HTTP ⻓连接。
TCP 的 Keepalive,是由 TCP 层(内核态) 实现的,称为 TCP 保活机制;
通俗地说,就是TCP有⼀个定时任务做倒计时,超时后会触发任务,内容是发送⼀个探测报⽂给对端,⽤来判断对端是否存活。
问题4
HTTP和HTTPS的区别
TCP连接确保可靠性⽅法如下:
1. 数据块⼤⼩控制: 应⽤数据被分割成TCP认为最合适发送的数据块,再传输给⽹络层,数据块被称为报⽂段或段。
2. 序列号: TCP给每个数据包指定序列号,接收⽅根据序列号对数据包进⾏排序,并根据序列号对数据包去重。
3. 校验和: TCP将保持它⾸部和数据的校验和。这是⼀个端到端的检验和,⽬的是检测数据在传输过程中的任何变化。如果收到报⽂的检验和有差错,TCP将丢弃这个报⽂段和不确认收到此报⽂段。
4. 流量控制: TCP连接的每⼀⽅都有固定⼤⼩的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收⽅来不及处理发送⽅的数据,能提示发送⽅降低发送的速率,防⽌包丢失。TCP利⽤滑动窗⼝实现流量控制。
5. 拥塞控制: 当⽹络拥塞时,减少数据的发送。
6. 确认应答: 通过 ARQ 协议实现。基本原理是每发完⼀个分组就停⽌发送,等待对⽅确认。如果没收到确认,会重发数据包,直到确认后再发下⼀个分组。
7. 超时重传: 当TCP发出⼀个数据段后,它启动⼀个定时器,等待⽬的端确认收到这个报⽂
段。如果不能及时收到⼀个确认,将重发这个报⽂段。
问题5
拥塞控制算法主要有以下⼏种:
1. 慢启动
在连接刚开始时,发送⽅会逐渐增加发送窗⼝⼤⼩,从⽽以指数增⻓的速度增加发送的数据量。
2. 拥塞避免
⼀旦慢启动阶段过去,发送⽅进⼊拥塞避免阶段。在这个阶段,发送⽅逐渐增加发送窗⼝的⼤
⼩,但增加速率较慢,避免过快增加导致⽹络拥塞。
3. 超时重传
如果发送⽅在超时时间内未收到确认,它会认为数据包丢失,并重传这些数据包。这是拥塞控制
的最后⼿段,⽤于检测和处理⽹络中的丢包或拥塞情况。当⽹络出现拥塞,也就是会发⽣数据包重传
4. 快速重传(Fast Retransmit)和快速恢复(Fast Recovery)
当发送⽅发送的数据包丢失或⽹络出现拥塞时,接收⽅会发送重复确认(duplicate ACK)通知
发送⽅有数据包丢失。当发送⽅收到⼀定数量的重复确认时,它会⽴即重传丢失的数据包,⽽不是等待超时。这样可以减少⽹络的拥塞程度。
5. 拥塞窗⼝调整
发送⽅根据⽹络的拥塞程度动态调整发送窗⼝的⼤⼩,通过监测⽹络延迟和丢包情况来确定合适
的发送速率,以避免⽹络拥塞
问题6
Cookie 和 Session 都⽤于管理⽤户的状态和身份, Cookie 通过在客户端记录信息确定⽤户
身份, Session 通过在服务器端记录信息确定⽤户身份。
Cookie 是存储在⽤户浏览器中的⼩型⽂本⽂件,⽤于在⽤户和服务器之间传递数据。通常,服务器会将⼀个或多个 Cookie 发送到⽤户浏览器,然后浏览器将这些 Cookie 存储在本地。
服务器在接收到来⾃客户端浏览器的请求之后,就能够通过分析存放于请求头的Cookie得到客户端特有的信息,从⽽动态⽣成与该客户端相对应的内容。
客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是 Session 。Session 主要⽤于维护⽤户登录状态、存储⽤户的临时数据和上下⽂信息等。
不同点
存储位置:Cookie 数据存储在⽤户的浏览器中,⽽ Session 数据存储在服务器上。
数据容量:Cookie 存储容量较⼩,⼀般为⼏ KB。Session 存储容量较⼤,通常没有固定
限制,取决于服务器的配置和资源。
安全性:由于 Cookie 存储在⽤户浏览器中,因此可以被⽤户读取和篡改。相⽐之下,
Session 数据存储在服务器上,更难被⽤户访问和修改。
传输⽅式:Cookie 在每次 HTTP 请求中都会被⾃动发送到服务器,⽽ Session ID 通常通
过 Cookie 或 URL 参数传递。
问题7
进程同步是指多个并发执⾏的进程之间协调和管理它们的执⾏顺序,以确保它们按照⼀定的顺序或时间间隔执⾏。
互斥指的是在某⼀时刻只允许⼀个进程访问某个共享资源。当⼀个进程正在使⽤共享资源时,其他进程不能同时访问该资源。
解决进程同步和互斥的问题有很多种⽅法,其中⼀种常⻅的⽅法是使⽤信号量和 PV 操作。
信号量是⼀种特殊的变量,它表示系统中某种资源的数量或者状态。PV 操作是⼀种对信号量进⾏增加或者减少的操作,它们可以⽤来控制进程之间的同步或者互斥。
除此之外,下⾯的⽅法也可以解决进程同步和互斥问题:
1.临界区(Critical Section): 将可能引发互斥问题的代码段称为临界区。为了实现互斥,每个进程在进⼊临界区前必须获取⼀个锁,退出临界区后释放该锁。这确保同⼀时间只有⼀个进程可以进⼊临界区。
2.互斥锁(Mutex): 互斥锁是⼀种同步机制,⽤于实现互斥。每个共享资源都关联⼀个互斥锁,进程在访问该资源前需要先获取互斥锁,使⽤完后释放锁。只有获得锁的进程才能访问共享资源。
3.条件变量(Condition Variable): 条件变量⽤于在进程之间传递信息,以便它们在特定条件下等待或唤醒。通常与互斥锁⼀起使⽤,以确保等待和唤醒的操作在正确的时机执⾏。
问题8
中断和异常是两种不同的事件,它们都会导致CPU暂停当前的程序执⾏,转⽽去执⾏⼀个特定的处理程序。
中断和异常的区别主要有以下⼏点:
1.中断是由外部设备或其他处理器产⽣的,它们通常是异步的,也就是说,它们可以在任何时候发⽣,与当前执⾏的指令⽆关。例如,键盘输⼊、⿏标移动、⽹络数据到达等都会产⽣中断信号,通知CPU去处理这些事件。
异常是由CPU内部产⽣的,它们通常是同步的,也就是说,它们只会在执⾏某些指令时发⽣,与当前执⾏的指令有关。例如,除法运算时除数为零、访问⾮法内存地址、执⾏⾮法指令等都会产⽣异常信号,通知CPU去处理这些错误或故障。
2.中断可以被屏蔽或禁⽌,这意味着CPU可以通过设置某些标志位或寄存器来忽略或延迟响应某些中断信号。这样可以避免中断过于频繁或⼲扰重要的任务。异常不能被屏蔽或禁⽌,这意味着CPU必须⽴即响应异常信号,并进⾏相应的处理。这样可以保证程序的正确性和系统的稳定性。
问题9
线程同步机制是指在多线程编程中,为了保证线程之间的互不⼲扰,⽽采⽤的⼀种机制。常⻅的线程同步机制有以下⼏种:
1. 互斥锁:互斥锁是最常⻅的线程同步机制。它允许只有⼀个线程同时访问被保护的临界区(共享资源)
2. 条件变量:条件变量⽤于线程间通信,允许⼀个线程等待某个条件满⾜,⽽其他线程可以发出信号通知等待线程。通常与互斥锁⼀起使⽤。
3. 读写锁: 读写锁允许多个线程同时读取共享资源,但只允许⼀个线程写⼊资源。
4. 信号量:⽤于控制多个线程对共享资源进⾏访问的⼯具。
问题10
主要有MyISAM、InnoDB、Memery等引擎:
InnoDB 引擎提供了对事务ACID的⽀持,还提供了⾏级锁和外键的约束。
MyISAM 引擎不⽀持事务,也不⽀持⾏级锁和外键约束。
Memery 就是将数据放在内存中,数据处理速度很快,但是安全性不⾼。
问题11
MYSQL的日志文件有如下4种
- undo log 是 Innodb 存储引擎层⽣成的⽇志,实现了事务中的原⼦性,主要⽤于事务回滚和MVCC。
- redo log 是物理⽇志,记录了某个数据⻚做了什么修改,每当执⾏⼀个事务就会产⽣⼀条或者多条物理⽇志。
- binlog (归档⽇志)是Server 层⽣成的⽇志,主要⽤于数据备份和主从复制。
- relay log 中继⽇志,⽤于主从复制场景下, slave 通过io线程拷⻉master的 binlog 后本地⽣成的⽇志
问题12
MYSQL锁的类型
1. 全局锁
全局锁主要应⽤于做全库逻辑备份,这样在备份数据库期间,不会因为数据或表结构的更新,
⽽出现备份⽂件的数据与预期的不⼀样,加上全局锁,意味着整个数据库都是只读状态。
2. 表级锁
- 元数据锁(MDL):对数据库表进⾏操作时,会⾃动给这个表加上元数据锁,为了保证当⽤户对表执⾏ CRUD 操作时,其他线程对这个表结构做了变更。元数据锁在事务提交后才会释放。
- 意向锁:对某些记录加上共享锁之前,需要先在表级别加上⼀个意向共享锁,对某些纪录加上独占锁之前,需要先在表级别加上⼀个意向独占锁。普通的 select 是不会加⾏级锁的,普通的 select 语句是利⽤ MVCC 实现⼀致性读,是⽆锁的。
- AUTO-INC 锁:表⾥的主键通常都会设置成⾃增的,之后可以在插⼊数据时,可以不指定主键的值,数据库会⾃动给主键赋值递增的值通过 AUTO-INC 锁实现的。在插⼊数据时,会加⼀个表级别的 AUTO-INC 锁,然后为被 AUTO_INCREMENT 修饰的字段赋值递增的值,等插⼊语句执⾏完成后,才会把 AUTO-INC 锁释放掉。其他事务的如果要向该表插⼊语句都会被阻塞,从⽽保证插⼊数据时字段的值是连续递增的。
3. ⾏锁
- 记录锁:锁住的是⼀条记录,记录锁分为排他锁和共享锁。
- 间隙锁:只存在于可重复读隔离级别,⽬的是为了解决可重复读隔离级别下幻读的现象。间隙锁之间是兼容的,两个事务可以同时持有包含共同间隙范围的间隙锁,并不存在互斥关系。
- Next-Key Lock:Next-Key Lock临键锁,是 Record Lock + Gap Lock 的组合,锁定⼀个范围,并且锁定记录本身。next-key lock 即能保护该记录,⼜能阻⽌其他事务将新纪录插⼊到被保护记录前⾯的间隙中。
- 插⼊意向锁:⼀个事务在插⼊⼀条记录的时候,需要判断插⼊位置是否已被其他事务加了间隙锁(next-key lock 也包含间隙锁)。如果有的话,插⼊操作就会发⽣阻塞,直到拥有间隙锁的那个事务提交为⽌,在此期间会⽣成⼀个插⼊意向锁,表明有事务想在某个区间插⼊新记录,但是现在处于等待状态。
写在最后
PS:以上是网络上收集的一些常见的问题以及自己对答案搜索整理;一次整理基本上就是面试一次的题量,适合对自己的知识的查缺补漏
面试一般根据岗位要求或者简历上写的来进行扩展提问,也有些是直接问公司常用到的相关方面的技术问题,无论怎么准备都祝大家能拿到心怡的offer!