总结
难度:⭐⭐⭐⭐⭐ 学到的知识:⭐⭐⭐⭐☆
算法
题目描述
String转Long,需要考虑各种异常情况。
设计测试用例。
一些要点
Java中,int占4个字节,long占8个字节。以long为例,其取值范围为$$-2^{63}到2^{63}-1$$,不要轻易对下界取反,因为会溢出。 Java中提供了Long.MAX_VAlUE和Long.MIN_VALUE来获取long的上下界。 其他类型,byte(非bit)占1字节,short占2字节,float 4字节,double 8字节,char 2字节。 对象占几个字节?
Class MaNong {
int count;
boolean flag;
Object obj;
}
对象头(8字节/16字节)+ int(4字节)+ boolean(1字节)+ 空引用(4字节/8字节)= 17字节。 Java对象内存分配时以8的整数分配(对齐填充,以提高访问速度),故会分配24字节。 其中空引用类型,32位jvm是4字节,64位jvm是8字节,如果启动了压缩oops(限制堆大小,最大让其寻址32G内存),仍可能是4字节。 包装类占几个字节? 和对象一样,对象头 + 基本数据类型 + 对齐填充。
代码
public class BilibiliExamThree {
public static void main(String[] args) {
try {
System.out.println(StringToLong("1234"));
System.out.println(StringToLong("-12233"));
System.out.println(StringToLong("9223372036854775807"));
System.out.println(StringToLong("9223372036854775809")); //溢出
System.out.println(StringToLong("+"));
System.out.println(StringToLong("122c2234a"));
System.out.println(StringToLong("abc"));
System.out.println(StringToLong(""));
} catch (Exception e) {
e.printStackTrace();
}
}
public static long StringToLong(String string) throws Exception {
if (string == null || string.trim().isEmpty()) {
throw new NumberFormatException("输入的字符串为空,或仅包含空白字符");
}
string = string.trim();
long res = 0;
boolean isNegative = false;
int start = 0;
if (string.charAt(0) == '-' || string.charAt(0) == '+') {
start = 1;
if (string.charAt(0) == '-') isNegative = true;
}
if (start == 1 && string.length() == 1) {
throw new Exception("输入的字符串仅包含正负号。");
}
// MIN_VALUE的绝对值大于MAX_VALUE,不能对MIN_VALUE取反,否则会溢出
long limit = isNegative ? Long.MIN_VALUE : -Long.MAX_VALUE;
long multmin = limit / 10;
for (int i = start; i < string.length(); i++) {
char ch = string.charAt(i);
//判断是否是否合法
if (ch < '0' || ch > '9') {
throw new NumberFormatException("输入的字符串不合法");
}
// 判断是否超过long类型的界限
if (res < multmin) {
throw new NumberFormatException("超过long类型的界限。");
}
res *= 10;
// 判断是否超过long类型的界限
int nextDigit = ch - '0';
if (res < limit + nextDigit) {
throw new NumberFormatException("超过long类型的界限。");
}
res -= nextDigit;
}
if (!isNegative) res = -res;
return res;
}
}
数据库
1. 写一段会让数据库死锁的代码?
在互相持有对方需要的资源,且资源独占时会死锁。
-- 会话1
start transaction;
update tableA set id = 2 where id = 1;
--会话2
start transaction;
update tableB set id = 2 where id = 1;
update tableA set id = 3 where id = 2; -- 这里会等待,因为会话1已经将这行锁定
--回到会话1
update tableB set id = 3 where id = 2; --这里会产生死锁,因为会话2已经将这行锁定
--
innodb有一个死锁检测机制,他在检测到死锁时,会中断其中一个事务,从而解决死锁。上述两个事务中,其中一个会收到死锁的错误消息。
操作系统
1. 什么是哲学家就餐问题?如何解决?--mark,看视频学习下
并发和死锁问题。 解决方式:
- 仲裁串行化:任何时候只有一个哲学家在尝试拿叉子
- 限制同时尝试的哲学家数量:每次最多4位哲学家就餐(总共5个),这样至少有一个哲学家会成功。
- 随机等待:如果不能拿到全部的叉子,则随机等待一段时间再尝试
- 资源分级
数据结构
1. 如何设计一个哈希表?
- 选择哈希函数
- 好的哈希函数是关键,将输入均匀地映射到哈希表的索引。
- 快速计算,保持哈希表操作的高效性
- 数组或桶来存储数据
- 处理哈希冲突
- 链地址法
- 开放寻址法(顺序,跳跃,双重哈希)
- 动态调整大小
- 在加载因子超过一定的阈值,需要进行扩容。
- 删除操作
- 如果在开放定址法中,会标记已删除,如果直接删除,会中断其他键的探测序列。
- 其他:
- 设计合理的加载因子阈值
- 安全性:使用加密哈希函数或其他安全措施来避免恶意攻击(例如故意制造哈希冲突)
2. 如何解决哈希冲突?
- 开放寻址
- 链地址法
网络
1. 服务器发送rst的情况?
rst(reset)包是一种特殊的包,用于快速、无条件的终止连接,而无需tcp正常的终止序列(fin握手),在以下情况中使用。
- 异常关闭:当一个端点检测到连接中的错误或异常,可能会发送一个rst包来立即终止连接。
- 非预期的数据:如果一个端点接收到它不期望的数据(比如,认为连接已经关闭,但突然收到了数据,半开问题),他会回应一个rst包。
2. tcp如何只允许单方面发送消息?
通过tcp的半关闭或半开来实现,允许一个方向上的数据传输被关闭,另一个方向的数据传输保持打开。
- 半关闭 - tcp的正常特性 四次挥手中,客户端发送了fin报文,但是接收端仍有数据要发送,不发送fin报文,来保持办关闭状态。
- 半开 - 异常状态 由网络问题或其他中断导致。 半开状态中,一方认为连接仍然是打开并尝试发送数据,而另一方认为连接已经关闭。 这种状态是由FIN或RST包在网络中丢失导致的。 半开连接会导致资源泄露或其他问题,因为其中一方会为它认为仍然打开的链接保持资源。 半开状态下,若客户端已经断开,服务器不知道连接关闭,服务器尝试向客户端发送数据时,客户端会响应一个RST包。 解决:许多服务器有超时机制,如果一段时间内没有从连接中接收到任何数据,会自动关闭连接。
python
1. python多线程有什么问题?
python的实现中,使用了GIL互斥锁,来防止多个线程同时执行python字节码,也就说在任何给定的时间点,只有一个线程可以在解释器中执行。 由于gil的存在,多线程在cpu密集型任务上不会提供的预期的性能提升,因为线程不能并行的在多个cpu核心上运行。
python为什么要引入GIL呢?
- 取消复杂的锁机制,并提升了单线程程序的性能。
- cpython的内存管理使用的是引用计数,对引用计数的增减需要同步,GIL可以确保在任何时候只有一个线程能够修改引用计数。
- 历史原因:GIL最初被引入时,多核cpu并不那么普及。(GIL在90年代引入,盛业多核cpu在2001发布。)
- 早期的c扩展和库并不是线程安全,GIL提供一种方式来确保这些库在多线程环境中安全使用,而无需大量修改。
如何解决了GIL存在的问题?
- 使用其他Python实现,jpython,ironpython
- 使用多进程
- 子解释器,创建多个解释器,每个解释器有自己的GIL
django
1. django的设计思路是什么?
dango的设计思路是提供一个全面、集成的框架,让开发者可以快速、快速地开发出健壮、安全、可维护的web应用。 几个关键点:
- MTV架构
- Model:数据结构,数据库操作
- Template:在web页面中显示数据,定义了静态部分和动态部分的呈现方式
- View: 如何处理用户的输入并返回适当的响应。
- DRY:鼓励代码重用
- 约定由于配置:允许开发者快速开始而无需进行大量配置。
- 简化开发任务:内置轻量级web服务器、自动化的数据库迁移工具,管理界面生成器,这些都可以简化开发任务
- 可扩展性: 使用模块化的设计,开发者可以轻松地添加自己的应用程序或使用第三方应用。
松散耦合的体现
- 视图和模板逻辑分开,视图负责处理业务逻辑和决定哪些数据需要显示,而模板负责如何显示这些数据,因为视图和模板逻辑分开,可以独立修改和测试。
- 鼓励开发者构造可重用的应用程序,例如可以为用户身份验证创建一个应用程序,可以在多个Django项目中重用,而不需要做大量的更改。
MTV与MVC的不同? 主要讲一下MVC的各部分。 Model:一致,都是数据存储、检索和业务逻辑 View:如何将数据展示给用户,很多都是模板+数据 Controller:负责接收用户的请求,调用模型进程数据操作,然后选择使用哪个视图来显示结果给用户。
都是为了责任分离,django更强调模板,他只用于定义如何显示内容,而不涉及决定哪些内容要显示。
其他
1. 最近在看的一本书?讲下印象最深刻的地方?
《代码整洁之道》 "最好额注释是不需要注释的代码" "代码并不补偿糟糕的代码" "当代码无法明确地传达某个意图或背后的原因时,注释是有用的,例如解释某个复杂算法的原理或者为什么采取非常规的做法。" "避免误导性的代码,保证代码和注释一致,错误过时的注释比没有注释还操作" "不要在注释中重复代码,比如对代码做字面翻译" "函数和变量的良好命名可以减少对注释的需求。"