Skip to content

Commit

Permalink
kuaishou
Browse files Browse the repository at this point in the history
  • Loading branch information
itwanger committed Jun 20, 2024
1 parent 4fb8cc6 commit 21412f4
Show file tree
Hide file tree
Showing 9 changed files with 263 additions and 154 deletions.
9 changes: 9 additions & 0 deletions docs/sidebar/sanfene/collection.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,16 @@ CopyOnWriteArrayList list = new CopyOnWriteArrayList();

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

#### ArrayList 和 Vector 的区别?

Vector 属于 JDK 1.0 时期的遗留类,已不推荐使用,仍然保留着是因为 Java 希望向后兼容。

ArrayList 是在 JDK 1.2 时引入的,用于替代 Vector 作为主要的非同步动态数组实现。因为 Vector 所有的方法都使用 synchronized 关键字进行了同步,单线程环境下效率较低。

![二哥的 Java 进阶之路:Vector源码](https://cdn.tobebetterjavaer.com/stutymore/collection-20240619110254.png)

> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的招商银行面经同学 6 招银网络科技面试原题:线程不安全的集合变成线程安全的方法?
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的 比亚迪面经同学2面试原题:ArrayList 和 vector 的区别
### 7.CopyOnWriteArrayList 了解多少?

Expand Down
39 changes: 36 additions & 3 deletions docs/sidebar/sanfene/javase.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ Java 基本数据类型的默认值和占用大小:

| 数据类型 | 默认值 | 大小 |
| -------- | -------- | ------ |
| boolean | false | 不确定 |
| boolean | false | 1字节或 4 字节 |
| char | '\u0000' | 2 字节 |
| byte | 0 | 1 字节 |
| short | 0 | 2 字节 |
Expand Down Expand Up @@ -624,7 +624,7 @@ public Person(String name,int age){
}
```

3. 引用本类的构造函数
3. 引用本类的构造方法

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

Expand Down Expand Up @@ -676,6 +676,39 @@ public class Dog extends Animal {

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

#### 抽象类和普通类的区别?

抽象类使用 abstract 关键字定义,不能被实例化,只能作为其他类的父类。普通类没有 abstract 关键字,可以直接实例化。

抽象类可以包含抽象方法和非抽象方法。抽象方法没有方法体,必须由子类实现。普通类智能包含非抽象方法。

```java
abstract class Animal {
// 抽象方法
public abstract void makeSound();

// 非抽象方法
public void eat() {
System.out.println("This animal is eating.");
}
}

class Dog extends Animal {
// 实现抽象方法
@Override
public void makeSound() {
System.out.println("Woof");
}
}

public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.makeSound(); // 输出 "Woof"
dog.eat(); // 输出 "This animal is eating."
}
}
```

> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的小公司面经合集同学 1 Java 后端面试原题:抽象类和接口有什么区别?
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的用友面试原题:抽象类和接口的区别?抽象类可以定义构造方法吗?
Expand Down Expand Up @@ -1557,7 +1590,7 @@ throws 用在方法上,后面跟的是异常类,可以跟多个;而 throw
//包含可能会出现异常的代码以及声明异常的方法
}catch(Exception e) {
//捕获异常并进行处理
}finally { }
}finally {
//可选,必执行的代码
}
```
Expand Down
25 changes: 19 additions & 6 deletions docs/sidebar/sanfene/javathread.md
Original file line number Diff line number Diff line change
Expand Up @@ -1428,9 +1428,16 @@ volatile int x = 0

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

#### volatile和synchronized的区别

volatile 关键字用于修饰变量,确保该变量的更新操作对所有线程是可见的,即一旦某个线程修改了 volatile 变量,其他线程会立即看到最新的值。

synchronized 关键字用于修饰方法或代码块,确保同一时刻只有一个线程能够执行该方法或代码块,从而实现互斥访问。

> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的腾讯云智面经同学 16 一面面试原题:手写单例的过程中提到了 synchronized 和 volatile,顺便问了这两个的实现原理
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的携程面经同学 1 Java 后端技术一面面试原题:volatile 如何保证可见性(cup 缓存和主缓存)
> 3. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的 360 面经同学 3 Java 后端技术一面面试原题:volatile 关键字,说说别的你知道的关键字
> 4. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的快手面经同学 5 面试原题:synchronized和volatile的区别
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/)

Expand Down Expand Up @@ -1560,27 +1567,33 @@ ObjectMonitor() {

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

> synchronized 怎么保证可见性?
#### synchronized 怎么保证可见性?

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

> synchronized 怎么保证有序性?
#### synchronized 怎么保证有序性?

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

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

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

> synchronized 怎么实现可重入的呢?
#### synchronized 怎么实现可重入的呢?

可重入意味着同一个线程可以多次获得同一个锁,而不会被阻塞。具体来说,如果一个线程已经持有某个锁,那么它可以再次进入该锁保护的代码块或方法,而不会被阻塞。

synchronized 之所以支持可重入,是因为 Java 的对象头包含了一个 Mark Word,用于存储对象的状态,包括锁信息。

当一个线程获取对象锁时,JVM 会将该线程的 ID 写入 Mark Word,并将锁计数器设为 1。

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

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

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

Expand Down
22 changes: 13 additions & 9 deletions docs/sidebar/sanfene/jvm.md
Original file line number Diff line number Diff line change
Expand Up @@ -903,15 +903,19 @@ G1 收集器的运行过程大致可划分为这几个步骤:
### 28.有了 CMS,为什么还要引入 G1?

优点:CMS 最主要的优点在名字上已经体现出来——并发收集、低停顿。

缺点:CMS 同样有三个明显的缺点。

- Mark Sweep 算法会导致内存碎片比较多
- CMS 的并发能力比较依赖于 CPU 资源,并发回收时垃圾收集线程可能会抢占用户线程的资源,导致用户程序性能下降。
- 并发清除阶段,用户线程依然在运行,会产生所谓的理“浮动垃圾”(Floating Garbage),本次垃圾收集无法处理浮动垃圾,必须到下一次垃圾收集才能处理。如果浮动垃圾太多,会触发新的垃圾回收,导致性能降低。

G1 主要解决了内存碎片过多的问题。
| 特性 | CMS | G1 |
|------------------|-------------------------------|-----------------------------|
| 设计目标 | 低停顿时间 | 可预测的停顿时间 |
| 并发性 |||
| 内存碎片 | 是,容易产生碎片 | 否,通过区域划分和压缩减少碎片 |
| 收集代数 | 年轻代和老年代 | 整个堆,但区分年轻代和老年代 |
| 并发阶段 | 并发标记、并发清理 | 并发标记、并发清理、并发回收 |
| 停顿时间预测 | 较难预测 | 可配置停顿时间目标 |
| 容易出现的问题 | 内存碎片、Concurrent Mode Failure | 较少出现长时间停顿 |

CMS 适用于对延迟敏感的应用场景,主要目标是减少停顿时间,但容易产生内存碎片。G1 则提供了更好的停顿时间预测和内存压缩能力,适用于大内存和多核处理器环境。

> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的快手面经同学 5 面试原题:CMS垃圾收集器和G1垃圾收集器什么区别
### 29.你们线上用的什么垃圾收集器?为什么要用它?

Expand Down
26 changes: 23 additions & 3 deletions docs/sidebar/sanfene/mysql.md
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,27 @@ SQL 执行过程中,优化器通过成本计算预估出执行效率最高的
EXPLAIN SELECT * FROM your_table WHERE conditions;
```

#### 慢sql日志怎么开启?

慢 SQL 日志的开启方式有多种,比如说直接编辑 MySQL 的配置文件 my.cnf 或 my.ini,设置 slow_query_log 参数为 1,设置 slow_query_log_file 参数为慢查询日志的路径,设置 long_query_time 参数为慢查询的时间阈值。

```ini
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2 # 记录执行时间超过2秒的查询
```

然后重启 MySQL 服务就好了,也可以通过 set global 命令动态设置。

```sql
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
SET GLOBAL long_query_time = 2;
```

> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的腾讯云智面经同学 16 一面面试原题:场景题:sql 查询很慢怎么排查
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的快手面经同学 5 面试原题:慢sql日志怎么开启?
### 25.有哪些方式优化 SQL?

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

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

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

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

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

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

Expand Down
2 changes: 1 addition & 1 deletion docs/sidebar/sanfene/network.md
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ HTTP/2.0 基于 TCP 协议,而 HTTP/3.0 则基于 QUIC 协议,Quick UDP Conn

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

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

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

Expand Down
2 changes: 1 addition & 1 deletion docs/sidebar/sanfene/redis.md
Original file line number Diff line number Diff line change
Expand Up @@ -1687,7 +1687,7 @@ SET key value NX PX 30000

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

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

Expand Down
Loading

0 comments on commit 21412f4

Please sign in to comment.