Skip to content

Commit 21412f4

Browse files
committed
kuaishou
1 parent 4fb8cc6 commit 21412f4

File tree

9 files changed

+263
-154
lines changed

9 files changed

+263
-154
lines changed

docs/sidebar/sanfene/collection.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,16 @@ CopyOnWriteArrayList list = new CopyOnWriteArrayList();
321321

322322
通俗的讲,CopyOnWrite 就是当我们往一个容器添加元素的时候,不直接往容器中添加,而是先复制出一个新的容器,然后在新的容器里添加元素,添加完之后,再将原容器的引用指向新的容器。多个线程在读的时候,不需要加锁,因为当前容器不会添加任何元素。这样就实现了线程安全。
323323

324+
#### ArrayList 和 Vector 的区别?
325+
326+
Vector 属于 JDK 1.0 时期的遗留类,已不推荐使用,仍然保留着是因为 Java 希望向后兼容。
327+
328+
ArrayList 是在 JDK 1.2 时引入的,用于替代 Vector 作为主要的非同步动态数组实现。因为 Vector 所有的方法都使用 synchronized 关键字进行了同步,单线程环境下效率较低。
329+
330+
![二哥的 Java 进阶之路:Vector源码](https://cdn.tobebetterjavaer.com/stutymore/collection-20240619110254.png)
331+
324332
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的招商银行面经同学 6 招银网络科技面试原题:线程不安全的集合变成线程安全的方法?
333+
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的 比亚迪面经同学2面试原题:ArrayList 和 vector 的区别
325334
326335
### 7.CopyOnWriteArrayList 了解多少?
327336

docs/sidebar/sanfene/javase.md

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ Java 基本数据类型的默认值和占用大小:
151151

152152
| 数据类型 | 默认值 | 大小 |
153153
| -------- | -------- | ------ |
154-
| boolean | false | 不确定 |
154+
| boolean | false | 1字节或 4 字节 |
155155
| char | '\u0000' | 2 字节 |
156156
| byte | 0 | 1 字节 |
157157
| short | 0 | 2 字节 |
@@ -624,7 +624,7 @@ public Person(String name,int age){
624624
}
625625
```
626626

627-
3. 引用本类的构造函数
627+
3. 引用本类的构造方法
628628

629629
### 21.抽象类和接口有什么区别?
630630

@@ -676,6 +676,39 @@ public class Dog extends Animal {
676676

677677
抽象是一种隐藏复杂性和只显示必要部分的技术。在面向对象编程中,抽象可以通过抽象类和接口实现。
678678

679+
#### 抽象类和普通类的区别?
680+
681+
抽象类使用 abstract 关键字定义,不能被实例化,只能作为其他类的父类。普通类没有 abstract 关键字,可以直接实例化。
682+
683+
抽象类可以包含抽象方法和非抽象方法。抽象方法没有方法体,必须由子类实现。普通类智能包含非抽象方法。
684+
685+
```java
686+
abstract class Animal {
687+
// 抽象方法
688+
public abstract void makeSound();
689+
690+
// 非抽象方法
691+
public void eat() {
692+
System.out.println("This animal is eating.");
693+
}
694+
}
695+
696+
class Dog extends Animal {
697+
// 实现抽象方法
698+
@Override
699+
public void makeSound() {
700+
System.out.println("Woof");
701+
}
702+
}
703+
704+
public class Test {
705+
public static void main(String[] args) {
706+
Dog dog = new Dog();
707+
dog.makeSound(); // 输出 "Woof"
708+
dog.eat(); // 输出 "This animal is eating."
709+
}
710+
}
711+
```
679712

680713
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的小公司面经合集同学 1 Java 后端面试原题:抽象类和接口有什么区别?
681714
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的用友面试原题:抽象类和接口的区别?抽象类可以定义构造方法吗?
@@ -1557,7 +1590,7 @@ throws 用在方法上,后面跟的是异常类,可以跟多个;而 throw
15571590
//包含可能会出现异常的代码以及声明异常的方法
15581591
}catch(Exception e) {
15591592
//捕获异常并进行处理
1560-
}finally { }
1593+
}finally {
15611594
//可选,必执行的代码
15621595
}
15631596
```

docs/sidebar/sanfene/javathread.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,9 +1428,16 @@ volatile int x = 0
14281428

14291429
这意味着 volatile 变量的写操作总是发生在任何后续读操作之前。
14301430

1431+
#### volatile和synchronized的区别
1432+
1433+
volatile 关键字用于修饰变量,确保该变量的更新操作对所有线程是可见的,即一旦某个线程修改了 volatile 变量,其他线程会立即看到最新的值。
1434+
1435+
synchronized 关键字用于修饰方法或代码块,确保同一时刻只有一个线程能够执行该方法或代码块,从而实现互斥访问。
1436+
14311437
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的腾讯云智面经同学 16 一面面试原题:手写单例的过程中提到了 synchronized 和 volatile,顺便问了这两个的实现原理
14321438
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的携程面经同学 1 Java 后端技术一面面试原题:volatile 如何保证可见性(cup 缓存和主缓存)
14331439
> 3. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的 360 面经同学 3 Java 后端技术一面面试原题:volatile 关键字,说说别的你知道的关键字
1440+
> 4. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的快手面经同学 5 面试原题:synchronized和volatile的区别
14341441
14351442
GitHub 上标星 10000+ 的开源知识库《[二哥的 Java 进阶之路](https://github.com/itwanger/toBeBetterJavaer)》第一版 PDF 终于来了!包括 Java 基础语法、数组&字符串、OOP、集合框架、Java IO、异常处理、Java 新特性、网络编程、NIO、并发编程、JVM 等等,共计 32 万余字,500+张手绘图,可以说是通俗易懂、风趣幽默……详情戳:[太赞了,GitHub 上标星 10000+ 的 Java 教程](https://javabetter.cn/overview/)
14361443

@@ -1560,27 +1567,33 @@ ObjectMonitor() {
15601567

15611568
### 26.除了原子性,synchronized 可见性,有序性,可重入性怎么实现?
15621569

1563-
> synchronized 怎么保证可见性?
1570+
#### synchronized 怎么保证可见性?
15641571

15651572
- 线程加锁前,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值。
15661573
- 线程加锁后,其它线程无法获取主内存中的共享变量。
15671574
- 线程解锁前,必须把共享变量的最新值刷新到主内存中。
15681575

1569-
> synchronized 怎么保证有序性?
1576+
#### synchronized 怎么保证有序性?
15701577

15711578
synchronized 同步的代码块,具有排他性,一次只能被一个线程拥有,所以 synchronized 保证同一时刻,代码是单线程执行的。
15721579

15731580
因为 as-if-serial 语义的存在,单线程的程序能保证最终结果是有序的,但是不保证不会指令重排。
15741581

15751582
所以 synchronized 保证的有序是执行结果的有序性,而不是防止指令重排的有序性。
15761583

1577-
> synchronized 怎么实现可重入的呢?
1584+
#### synchronized 怎么实现可重入的呢?
1585+
1586+
可重入意味着同一个线程可以多次获得同一个锁,而不会被阻塞。具体来说,如果一个线程已经持有某个锁,那么它可以再次进入该锁保护的代码块或方法,而不会被阻塞。
1587+
1588+
synchronized 之所以支持可重入,是因为 Java 的对象头包含了一个 Mark Word,用于存储对象的状态,包括锁信息。
1589+
1590+
当一个线程获取对象锁时,JVM 会将该线程的 ID 写入 Mark Word,并将锁计数器设为 1。
15781591

1579-
synchronized 是可重入锁,也就是说,允许一个线程二次请求自己持有对象锁的临界资源,这种情况称为可重入锁
1592+
如果一个线程尝试再次获取已经持有的锁,JVM 会检查 Mark Word 中的线程 ID。如果 ID 匹配,表示的是同一个线程,锁计数器递增
15801593

1581-
synchronized 锁对象的时候有个计数器,他会记录下线程获取锁的次数,在执行完对应的代码块之后,计数器就会-1,直到计数器清零,就释放锁了
1594+
当线程退出同步块时,锁计数器递减。如果计数器值为零,JVM 将锁标记为未持有状态,并清除线程 ID 信息
15821595

1583-
之所以,是可重入的。是因为 synchronized 锁对象有个计数器,会随着线程获取锁后 +1 计数,当线程执行完毕后 -1,直到清零释放锁。
1596+
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的快手面经同学 5 面试原题:synchronized可重入锁怎么实现的
15841597
15851598
### 27.锁升级?synchronized 优化了解吗?
15861599

docs/sidebar/sanfene/jvm.md

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -903,15 +903,19 @@ G1 收集器的运行过程大致可划分为这几个步骤:
903903
904904
### 28.有了 CMS,为什么还要引入 G1?
905905

906-
优点:CMS 最主要的优点在名字上已经体现出来——并发收集、低停顿。
907-
908-
缺点:CMS 同样有三个明显的缺点。
909-
910-
- Mark Sweep 算法会导致内存碎片比较多
911-
- CMS 的并发能力比较依赖于 CPU 资源,并发回收时垃圾收集线程可能会抢占用户线程的资源,导致用户程序性能下降。
912-
- 并发清除阶段,用户线程依然在运行,会产生所谓的理“浮动垃圾”(Floating Garbage),本次垃圾收集无法处理浮动垃圾,必须到下一次垃圾收集才能处理。如果浮动垃圾太多,会触发新的垃圾回收,导致性能降低。
913-
914-
G1 主要解决了内存碎片过多的问题。
906+
| 特性 | CMS | G1 |
907+
|------------------|-------------------------------|-----------------------------|
908+
| 设计目标 | 低停顿时间 | 可预测的停顿时间 |
909+
| 并发性 |||
910+
| 内存碎片 | 是,容易产生碎片 | 否,通过区域划分和压缩减少碎片 |
911+
| 收集代数 | 年轻代和老年代 | 整个堆,但区分年轻代和老年代 |
912+
| 并发阶段 | 并发标记、并发清理 | 并发标记、并发清理、并发回收 |
913+
| 停顿时间预测 | 较难预测 | 可配置停顿时间目标 |
914+
| 容易出现的问题 | 内存碎片、Concurrent Mode Failure | 较少出现长时间停顿 |
915+
916+
CMS 适用于对延迟敏感的应用场景,主要目标是减少停顿时间,但容易产生内存碎片。G1 则提供了更好的停顿时间预测和内存压缩能力,适用于大内存和多核处理器环境。
917+
918+
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的快手面经同学 5 面试原题:CMS垃圾收集器和G1垃圾收集器什么区别
915919
916920
### 29.你们线上用的什么垃圾收集器?为什么要用它?
917921

docs/sidebar/sanfene/mysql.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,7 +1080,27 @@ SQL 执行过程中,优化器通过成本计算预估出执行效率最高的
10801080
EXPLAIN SELECT * FROM your_table WHERE conditions;
10811081
```
10821082

1083+
#### 慢sql日志怎么开启?
1084+
1085+
慢 SQL 日志的开启方式有多种,比如说直接编辑 MySQL 的配置文件 my.cnf 或 my.ini,设置 slow_query_log 参数为 1,设置 slow_query_log_file 参数为慢查询日志的路径,设置 long_query_time 参数为慢查询的时间阈值。
1086+
1087+
```ini
1088+
[mysqld]
1089+
slow_query_log = 1
1090+
slow_query_log_file = /var/log/mysql/slow.log
1091+
long_query_time = 2 # 记录执行时间超过2秒的查询
1092+
```
1093+
1094+
然后重启 MySQL 服务就好了,也可以通过 set global 命令动态设置。
1095+
1096+
```sql
1097+
SET GLOBAL slow_query_log = 'ON';
1098+
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
1099+
SET GLOBAL long_query_time = 2;
1100+
```
1101+
10831102
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的腾讯云智面经同学 16 一面面试原题:场景题:sql 查询很慢怎么排查
1103+
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的快手面经同学 5 面试原题:慢sql日志怎么开启?
10841104
10851105
### 25.有哪些方式优化 SQL?
10861106

@@ -1868,13 +1888,13 @@ SELECT * FROM table WHERE column LIKE '%xxx%';
18681888
18691889
### 38.聚簇索引与非聚簇索引的区别?
18701890

1871-
聚簇索引不是一种新的索引,而是一种**数据存储方式**
1891+
在 MySQL 的 InnoDB 存储引擎中,主键就是聚簇索引。聚簇索引不是一种新的索引,而是一种**数据存储方式**
18721892

18731893
![三分恶面渣逆袭:聚簇索引和非聚簇索引](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/mysql-692cced2-615a-4b70-a933-69771d53e809.jpg)
18741894

1875-
在聚簇索引中,表中的行是按照键值(索引)的顺序存储的。这意味着表中的实际数据行和键值之间存在物理排序的关系。因此,每个表只能有一个聚簇索引。例如,在 MySQL 的 InnoDB 存储引擎中,主键就是聚簇索引。
1895+
在聚簇索引中,表中的行是按照键值(索引)的顺序存储的。这意味着表中的实际数据行和键值之间存在物理排序的关系。因此,每个表只能有一个聚簇索引。
18761896

1877-
在非聚簇索引中,索引和数据是分开存储的,索引中的键值指向数据的实际存储位置。因此,非聚簇索引也被称为二级索引或辅助索引。表可以有多个非聚簇索引。
1897+
在非聚簇索引中,索引和数据是分开存储的,索引中的键值指向数据的实际存储位置。因此,非聚簇索引也被称为二级索引或辅助索引或非主键索引。表可以有多个非聚簇索引。
18781898

18791899
这意味着,当使用非聚簇索引检索数据时,数据库首先在索引中查找,然后通过索引中的指针去访问表中实际的数据行,这个过程称为“回表”(Bookmark Lookup)。
18801900

docs/sidebar/sanfene/network.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ HTTP/2.0 基于 TCP 协议,而 HTTP/3.0 则基于 QUIC 协议,Quick UDP Conn
463463

464464
使用 HTTPS 主要是为了解决 HTTP 传输过程中的一些安全问题,因为 HTTP 是明文传输,所以 HTTPS 在 HTTP 的基础上加入了 SSL/TLS 协议。
465465

466-
![](https://cdn.tobebetterjavaer.com/stutymore/network-20240418120939.png)
466+
![二哥的 Java 进阶之路:http和 https 的区别](https://cdn.tobebetterjavaer.com/stutymore/network-20240418120939.png)
467467

468468
SSL(安全套接字)/TLS(传输层安全)协议可以用来加密通信内容,保证通信过程中的数据不被窃取和篡改。整个加密过程主要涉及两种类型的加密方法:
469469

docs/sidebar/sanfene/redis.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1687,7 +1687,7 @@ SET key value NX PX 30000
16871687

16881688
上面这段命令其实是 setnx 和 expire 组合在一起的原子命令,算是比较完善的一个分布式锁了。
16891689

1690-
当然,实际的开发中,没人会去自己写分布式锁的命令,因为有专业的轮子——[Redisson](https://xie.infoq.cn/article/d8e897f768eb1a358a0fd6300)。(戳链接跳转至悟空聊架构:分布式锁中的王者方案 - Redisson)
1690+
>当然,实际的开发中,没人会去自己写分布式锁的命令,因为有专业的轮子——[Redisson](https://xie.infoq.cn/article/d8e897f768eb1a358a0fd6300)。(戳链接跳转至悟空聊架构:分布式锁中的王者方案 - Redisson)
16911691
16921692
#### Redisson 了解吗?
16931693

0 commit comments

Comments
 (0)