Skip to content

Commit c7fdc21

Browse files
committed
京东面经
1 parent feb2bb1 commit c7fdc21

File tree

4 files changed

+187
-136
lines changed

4 files changed

+187
-136
lines changed

docs/src/sidebar/sanfene/javathread.md

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ head:
2020

2121
### 1.并行跟并发有什么区别?
2222

23-
- 并行是指多个处理器同时执行多个任务,每个核心实际上可以在同一时间独立地执行不同的任务
24-
- 并发是指系统有处理多个任务的能力,但是任意时刻只有一个任务在执行。在单核处理器上,多个任务是通过时间片轮转的方式实现的。但这种切换非常快,给人感觉是在同时执行
23+
- 并行:多核 CPU 上的多任务处理,多个任务在同一时间真正地同时执行
24+
- 并发:单核 CPU 上的多任务处理,多个任务在同一时间段内交替执行,通过时间片轮转实现交替执行
2525

2626
![三分恶面渣逆袭:并行和并发](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/javathread-1.png)
2727

@@ -2658,6 +2658,55 @@ CountDownLatch 的**核心方法**也不多:
26582658
- `void await()`:阻塞当前线程,直到计数器为零。
26592659
- `void countDown()`:递减计数器的值,如果计数器值变为零,则释放所有等待的线程。
26602660

2661+
#### 场景题:假如要查10万多条数据,用线程池分成20个线程去执行,怎么做到等所有的线程都查找完之后,即最后一条结果查找结束了,才输出结果?
2662+
2663+
为每个线程创建一个任务,使用 CountDownLatch 计数器控制线程同步。
2664+
2665+
每个线程任务完成后调用 `countDown()`,主线程使用 `await()` 等待所有线程完成。
2666+
2667+
```java
2668+
class DataQueryExample {
2669+
2670+
public static void main(String[] args) throws InterruptedException {
2671+
// 模拟10万条数据
2672+
int totalRecords = 100000;
2673+
int threadCount = 20;
2674+
int batchSize = totalRecords / threadCount; // 每个线程处理的数据量
2675+
2676+
// 创建线程池
2677+
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
2678+
CountDownLatch latch = new CountDownLatch(threadCount);
2679+
2680+
// 模拟查询结果
2681+
ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
2682+
2683+
for (int i = 0; i < threadCount; i++) {
2684+
int start = i * batchSize;
2685+
int end = (i == threadCount - 1) ? totalRecords : (start + batchSize);
2686+
2687+
executor.execute(() -> {
2688+
try {
2689+
// 模拟查询操作
2690+
for (int j = start; j < end; j++) {
2691+
results.add("Data-" + j);
2692+
}
2693+
System.out.println(Thread.currentThread().getName() + " 处理数据 " + start + " - " + end);
2694+
} finally {
2695+
latch.countDown(); // 线程任务完成,计数器减1
2696+
}
2697+
});
2698+
}
2699+
2700+
// 等待所有线程完成
2701+
latch.await();
2702+
executor.shutdown();
2703+
2704+
// 输出结果
2705+
System.out.println("所有线程执行完毕,查询结果总数:" + results.size());
2706+
}
2707+
}
2708+
```
2709+
26612710
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的顺丰科技同学 1 面试原题:并发编程 CountDownLatch 和消息队列
26622711
26632712
### 44.CyclicBarrier(同步屏障)了解吗?
@@ -3241,7 +3290,7 @@ public CompletableFutureBridge runAsyncWithTimeRecord(Runnable run, String name)
32413290
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的携程面经同学 10 Java 暑期实习一面面试原题:讲一讲你对线程池的理解,并讲一讲使用的场景
32423291
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的美团面经同学 4 一面面试原题:平时怎么使用多线程
32433292
3244-
### 55.能简单说一下线程池的工作流程吗
3293+
### 55.说一下线程池的工作流程
32453294

32463295
当应用程序提交一个任务时,线程池会根据当前线程的状态和参数决定如何处理这个任务。
32473296

@@ -3340,6 +3389,7 @@ public class ThreadPoolDemo {
33403389
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的美团面经同学 16 暑期实习一面面试原题:线程池核心参数,线程池工作模型
33413390
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的快手面经同学 1 部门主站技术部面试原题:向线程池中提交任务的过程?
33423391
> 3. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的招商银行面经同学 6 招银网络科技面试原题:JUC 并发编程中的 ThreadPoolExecutor 的拒绝策略什么时候发生?
3392+
> 4. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的京东面经同学 9 面试原题:线程池的工作原理?
33433393
33443394
### 56.线程池主要参数有哪些?
33453395

@@ -3427,7 +3477,7 @@ handler = ThreadPoolExecutor.AbortPolicy()
34273477

34283478
### 57.线程池的拒绝策略有哪些?
34293479

3430-
主要有四种
3480+
拒绝策略有四种
34313481

34323482
- AbortPolicy:这是默认的拒绝策略。该策略会抛出一个 RejectedExecutionException 异常。
34333483
- CallerRunsPolicy:该策略不会抛出异常,而是会让提交任务的线程(即调用 execute 方法的线程)自己来执行这个任务。
@@ -3477,10 +3527,15 @@ class CustomRejectedHandler {
34773527
}
34783528
```
34793529

3530+
#### 什么时候会执行拒绝策略?
3531+
3532+
当线程池无法接受新的任务时,也就是线程数达到 maximumPoolSize,任务队列也满了的时候,就会触发拒绝策略。
3533+
34803534
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的滴滴同学 2 技术二面的原题:说说并发编程中的拒绝策略,哪些情况对应用什么拒绝策略
34813535
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的美团面经同学 3 Java 后端技术一面面试原题:线程池怎么设计,拒绝策略有哪些,如何选择
34823536
> 3. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的美团面经同学 4 一面面试原题:饱和策略有哪几种
34833537
> 4. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的理想汽车面经同学 2 一面面试原题:线程池淘汰策略,追问:可以自定义淘汰策略吗?淘汰策略的实现类是啥?
3538+
> 5. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的京东面经同学 9 面试原题:什么时候会执行拒绝策略?
34843539
34853540
### 58.线程池有哪几种阻塞队列?
34863541

@@ -4042,11 +4097,6 @@ public class CustomRejectedExecutionHandler {
40424097
使用示例:
40434098

40444099
```java
4045-
package com.github.paicoding.forum.web.javabetter.thread1;
4046-
4047-
import java.util.concurrent.LinkedBlockingQueue;
4048-
import java.util.concurrent.TimeUnit;
4049-
40504100
public class ThreadPoolTest {
40514101
public static void main(String[] args) {
40524102
// Create a thread pool with core size 2, max size 4, and a queue capacity of 2
@@ -4179,6 +4229,7 @@ class SimpleConnectionPool {
41794229
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的美团面经同学 3 Java 后端技术一面面试原题:线程池怎么设计,拒绝策略有哪些,如何选择
41804230
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的哔哩哔哩同学 1 二面面试原题:给你一个需求,你需要写一个连接池,你现在可以写一下
41814231

4232+
41824233
### 70.单机线程池执行断电了应该怎么处理?
41834234

41844235
我们可以对正在处理和阻塞队列的任务做事务管理或者对阻塞队列中的任务持久化处理,并且当断电或者系统崩溃,操作无法继续下去的时候,可以通过回溯日志的方式来撤销`正在处理`的已经执行成功的操作。然后重新执行整个阻塞队列。

docs/src/sidebar/sanfene/jvm.md

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,13 @@ Java 的垃圾回收过程主要分为标记存活对象、清除无用对象、
890890
891891
### 24.如何判断对象仍然存活?
892892

893-
通常有两种方式:引用计数算法和可达性分析算法,Java 使用的是可达性分析算法。
893+
Java 通过可达性分析算法来判断一个对象是否还存活。
894+
895+
通过一组名为 “GC Roots” 的根对象,进行递归扫“”无法从根对象到达的对象就是“垃圾”,可以被回收。
896+
897+
![三分恶面渣逆袭:GC Root](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/jvm-18.png)
898+
899+
这也是 G1、CMS 等主流垃圾收集器使用的主要算法。
894900

895901
#### 什么是引用计数法?
896902

@@ -900,14 +906,6 @@ Java 的垃圾回收过程主要分为标记存活对象、清除无用对象、
900906

901907
但无法解决循环引用问题。例如,两个对象互相引用,但不再被其他对象引用,它们的引用计数都不为零,因此不会被回收。
902908

903-
#### 什么是可达性分析算法?
904-
905-
通过一组名为 “GC Roots” 的根对象,进行递归扫描。那些无法从根对象到达的对象是不可达的,可以被回收;反之,是可达的,不会被回收。
906-
907-
![三分恶面渣逆袭:GC Root](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/jvm-18.png)
908-
909-
这也是 G1、CMS 等主流垃圾收集器使用的主要算法。
910-
911909
#### 做可达性分析的时候,应该有哪些前置性的操作?
912910

913911
在进行垃圾回收之前,JVM 会暂停所有正在执行的应用线程(称为 Stop-the-World)。
@@ -916,6 +914,7 @@ Java 的垃圾回收过程主要分为标记存活对象、清除无用对象、
916914

917915
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的京东面经同学 7 京东到家面试原题:如何判断一个对象是否可以回收
918916
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的快手同学 2 一面面试原题:做可达性分析的时候,应该有哪些前置性的操作?
917+
> 3. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的京东面经同学 9 面试原题:什么样的对象算作垃圾对象
919918
920919

921920
### 25.Java 中可作为 GC Roots 的引用有哪几种?
@@ -1079,10 +1078,18 @@ public class ConstantPoolReference {
10791078

10801079
新生代的对象生命周期短,使用复制算法可以快速回收。老年代的对象生命周期长,使用标记-整理算法可以减少移动对象的成本。
10811080

1081+
#### 标记复制的标记过程和复制过程会不会停顿?
1082+
1083+
在标记-复制算法 中,标记阶段和复制阶段都会触发STW。
1084+
1085+
- 标记阶段停顿是为了保证对象的引用关系不被修改。
1086+
- 复制阶段停顿是防止对象在复制过程中被修改。
1087+
10821088
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的字节跳动面经同学 1 Java 后端技术一面面试原题:垃圾回收算法了解多少?
10831089
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的小米面经同学 F 面试原题:垃圾回收的算法及详细介绍
10841090
> 3. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的腾讯面经同学 27 云后台技术一面面试原题:回收的方法?分代收集算法里面具体是怎么回收的?为什么要用分代收集呢?
10851091
> 4. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的百度同学 4 面试原题:Gc 算法有哪些?
1092+
> 5. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的京东面经同学 9 面试原题:问了垃圾回收算法,针对问了每个算法的优缺点
10861093
10871094
### 28.Minor GC、Major GC、Mixed GC、Full GC 都是什么意思?
10881095

@@ -1169,15 +1176,15 @@ Serial Old 是 Serial 收集器的老年代版本,它同样是一个单线程
11691176

11701177
#### 说说 Parallel Old 收集器?
11711178

1172-
Parallel Old 是 Parallel Scavenge 收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实现。
1179+
Parallel Old 是 Parallel Scavenge 收集器的老年代版本,基于标记-整理算法实现,使用多条 GC 线程在 STW 期间同时进行垃圾回收
11731180

1174-
![Parallel Scavenge/Parallel Old收集器运行示意图](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/jvm-32.png)
1181+
![三分恶面渣逆袭:Parallel Old收集器](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/jvm-32.png)
11751182

11761183
#### 说说 CMS 收集器?
11771184

11781185
CMS 在 JDK 1.5 时引入,JDK 9 时被标记弃用,JDK 14 时被移除。
11791186

1180-
CMS 是一种低延迟的垃圾收集器,采用标记-清除算法,分为初始标记、并发标记、重新标记和并发清除四个阶段,优点是停顿时间短,适合延迟敏感的应用,但容易产生内存碎片,可能触发 Full GC。
1187+
CMS 是一种低延迟的垃圾收集器,采用标记-清除算法,分为初始标记、并发标记、重新标记和并发清除四个阶段,优点是垃圾回收线程和应用线程同时运行,停顿时间短,适合延迟敏感的应用,但容易产生内存碎片,可能触发 Full GC。
11811188

11821189
![小潘:CMS](https://cdn.tobebetterjavaer.com/stutymore/gc-collector-20231228211056.png)
11831190

@@ -1214,17 +1221,18 @@ ZGC 是 JDK 11 时引入的一款低延迟的垃圾收集器,最大特点是
12141221
> 4. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的京东同学 4 云实习面试原题:常见的 7 个 GC 回收器
12151222
> 5. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的美团面经同学 15 点评后端技术面试原题:讲一下知道的垃圾回收器,问知不知道ZGC回收器(不知道)
12161223
> 6. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的阿里云面经同学 22 面经:cms和g1的区别
1224+
> 7. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的京东面经同学 9 面试原题:怎么理解并发和并行,Parallel Old和CMS有什么区别?
12171225
12181226
### 32.能详细说一下 CMS 收集器的垃圾收集过程吗?
12191227

12201228
![三分恶面渣逆袭:Concurrent Mark Sweep收集器运行示意图](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/jvm-34.png)
12211229

1222-
CMS(Concurrent Mark Sweep)主要使用了**标记-清除**算法进行垃圾收集,分 4 大步:
1230+
CMS 使用**标记-清除**算法进行垃圾收集,分 4 大步:
12231231

1224-
- **初始标记**(Initial Mark):标记所有从 GC Roots 直接可达的对象,这个阶段需要 STW,但速度很快。
1225-
- **并发标记**(Concurrent Mark):从初始标记的对象出发,遍历所有对象,标记所有可达的对象。这个阶段是并发进行的,STW
1226-
- **重新标记**(Remark):完成剩余的标记工作,包括处理并发阶段遗留下来的少量变动,这个阶段通常需要短暂的 STW 停顿。
1227-
- **并发清除**(Concurrent Sweep):清除未被标记的对象,回收它们占用的内存空间。
1232+
- **初始标记**:标记所有从 GC Roots 直接可达的对象,这个阶段需要 STW,但速度很快。
1233+
- **并发标记**:从初始标记的对象出发,遍历所有对象,标记所有可达的对象。这个阶段是并发进行的。
1234+
- **重新标记**:完成剩余的标记工作,包括处理并发阶段遗留下来的少量变动,这个阶段通常需要短暂的 STW 停顿。
1235+
- **并发清除**:清除未被标记的对象,回收它们占用的内存空间。
12281236

12291237
#### 你提到了remark,那它remark具体是怎么执行的?三色标记法?
12301238

@@ -1263,6 +1271,7 @@ CMS(Concurrent Mark Sweep)主要使用了**标记-清除**算法进行垃圾
12631271
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的携程面经同学 10 Java 暑期实习一面面试原题:有哪些垃圾回收器,选一个讲一下垃圾回收的流程
12641272
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的携程面经同学 1 Java 后端技术一面面试原题:对象创建到销毁,内存如何分配的,(类加载和对象创建过程,CMS,G1 内存清理和分配)
12651273
> 3. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的收钱吧面经同学 1 Java 后端一面面试原题:CMS用了什么垃圾回收算法?你提到了remark,那它remark具体是怎么执行的?三色标记法?
1274+
> 4. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的京东面经同学 9 面试原题:问了CMS垃圾回收器
12661275
12671276
### 33.G1 垃圾收集器了解吗?
12681277

0 commit comments

Comments
 (0)