Skip to content

Commit eea8a1e

Browse files
authored
Merge pull request Snailclimb#1417 from Aaron-Ge/master
Update Java并发进阶常见面试题总结.md
2 parents f6e0428 + 3a90b25 commit eea8a1e

File tree

3 files changed

+14
-13
lines changed

3 files changed

+14
-13
lines changed

docs/java/multi-thread/Java并发进阶常见面试题总结.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ JDK1.6 对锁的实现引入了大量的优化,如偏向锁、轻量级锁、
286286
### 2.3. 并发编程的三个重要特性
287287

288288
1. **原子性** : 一个的操作或者多次操作,要么所有的操作全部都得到执行并且不会收到任何因素的干扰而中断,要么所有的操作都执行,要么都不执行。`synchronized` 可以保证代码片段的原子性。
289-
2. **可见性**当一个变量对共享变量进行了修改,那么另外的线程都是立即可以看到修改后的最新值。`volatile` 关键字可以保证共享变量的可见性。
289+
2. **可见性**当一个线程对共享变量进行了修改,那么另外的线程都是立即可以看到修改后的最新值。`volatile` 关键字可以保证共享变量的可见性。
290290
3. **有序性** :代码在执行的过程中的先后顺序,Java 在编译器以及运行期间的优化,代码的执行顺序未必就是编写代码时候的顺序。`volatile` 关键字可以禁止指令进行重排序优化。
291291

292292
### 2.4. 说说 synchronized 关键字和 volatile 关键字的区别
@@ -465,14 +465,14 @@ static class Entry extends WeakReference<ThreadLocal<?>> {
465465

466466
### 4.1. 为什么要用线程池?
467467

468-
> **池化技术相比大家已经屡见不鲜了,线程池、数据库连接池、Http 连接池等等都是对这个思想的应用。池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。**
468+
> **池化技术想必大家已经屡见不鲜了,线程池、数据库连接池、Http 连接池等等都是对这个思想的应用。池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。**
469469
470470
**线程池**提供了一种限制和管理资源(包括执行一个任务)。 每个**线程池**还维护一些基本统计信息,例如已完成任务的数量。
471471

472472
这里借用《Java 并发编程的艺术》提到的来说一下**使用线程池的好处**
473473

474474
- **降低资源消耗**。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
475-
- **提高响应速度**。当任务到达时,任务可以不需要的等到线程创建就能立即执行
475+
- **提高响应速度**。当任务到达时,任务可以不需要等到线程创建就能立即执行
476476
- **提高线程的可管理性**。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
477477

478478
### 4.2. 实现 Runnable 接口和 Callable 接口的区别
@@ -601,7 +601,7 @@ public ThreadPoolExecutor(int corePoolSize,
601601

602602
**`ThreadPoolExecutor` 3 个最重要的参数:**
603603

604-
- **`corePoolSize` :** 核心线程数线程数定义了最小可以同时运行的线程数量
604+
- **`corePoolSize` :** 核心线程数定义了最小可以同时运行的线程数量
605605
- **`maximumPoolSize` :** 当队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。
606606
- **`workQueue`:** 当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中。
607607

@@ -803,7 +803,7 @@ public void execute(Runnable command) {
803803

804804
![图解线程池实现原理](images/java线程池学习总结/图解线程池实现原理.png)
805805

806-
现在,让我们在回到 4.6 节我们写的 Demo, 现在应该是不是很容易就可以搞懂它的原理了呢
806+
现在,让我们在回到 4.6 节我们写的 Demo, 现在是不是很容易就可以搞懂它的原理了呢
807807

808808
没搞懂的话,也没关系,可以看看我的分析:
809809

@@ -919,7 +919,7 @@ AQS 的全称为(`AbstractQueuedSynchronizer`),这个类在` java.util.con
919919

920920
![AQS类](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/AQS类.png)
921921

922-
AQS 是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的 `ReentrantLock``Semaphore`,其他的诸如 `ReentrantReadWriteLock``SynchronousQueue``FutureTask` 等等皆是基于 AQS 的。当然,我们自己也能利用 AQS 非常轻松容易地构造出符合我们自己需求的同步器。
922+
AQS 是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出大量应用广泛的同步器,比如我们提到的 `ReentrantLock``Semaphore`,其他的诸如 `ReentrantReadWriteLock``SynchronousQueue``FutureTask` 等等皆是基于 AQS 的。当然,我们自己也能利用 AQS 非常轻松容易地构造出符合我们自己需求的同步器。
923923

924924
### 6.2. AQS 原理分析
925925

@@ -933,7 +933,7 @@ AQS 原理这部分参考了部分博客,在 5.2 节末尾放了链接。
933933

934934
**AQS 核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制 AQS 是用 CLH 队列锁实现的,即将暂时获取不到锁的线程加入到队列中。**
935935

936-
> CLH(Craig,Landin,and Hagersten)队列是一个虚拟的双向队列(虚拟的双向队列即不存在队列实例,仅存在结点之间的关联关系)。AQS 是将每条请求共享资源的线程封装成一个 CLH 锁队列的一个结点(Node)来实现锁的分配。
936+
> CLH(Craig,Landin and Hagersten)队列是一个虚拟的双向队列(虚拟的双向队列即不存在队列实例,仅存在结点之间的关联关系)。AQS 是将每条请求共享资源的线程封装成一个 CLH 锁队列的一个结点(Node)来实现锁的分配。
937937
938938
看个 AQS(AbstractQueuedSynchronizer)原理图:
939939

docs/java/multi-thread/java线程池学习总结.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747

4848
## 一 使用线程池的好处
4949

50-
> **池化技术相比大家已经屡见不鲜了,线程池、数据库连接池、Http 连接池等等都是对这个思想的应用。池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。**
50+
> **池化技术想必大家已经屡见不鲜了,线程池、数据库连接池、Http 连接池等等都是对这个思想的应用。池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。**
5151
5252
**线程池**提供了一种限制和管理资源(包括执行一个任务)。 每个**线程池**还维护一些基本统计信息,例如已完成任务的数量。
5353

@@ -184,7 +184,7 @@ public class ScheduledThreadPoolExecutor
184184
185185
### 3.2 推荐使用 `ThreadPoolExecutor` 构造函数创建线程池
186186

187-
**在《阿里巴巴 Java 开发手册》“并发处理”这一章节,明确指出线程资源必须通过线程池提供,不允许在应用中自行显示创建线程**
187+
**在《阿里巴巴 Java 开发手册》“并发处理”这一章节,明确指出线程资源必须通过线程池提供,不允许在应用中自行显式创建线程**
188188

189189
**为什么呢?**
190190

@@ -199,6 +199,7 @@ public class ScheduledThreadPoolExecutor
199199
200200
**方式一:通过`ThreadPoolExecutor`构造函数实现(推荐)**
201201
![通过构造方法实现](images/java线程池学习总结/threadpoolexecutor构造函数.png)
202+
202203
**方式二:通过 Executor 框架的工具类 Executors 来实现**
203204
我们可以创建三种类型的 ThreadPoolExecutor:
204205

@@ -879,7 +880,7 @@ Wed Nov 13 13:40:43 CST 2019::pool-1-thread-5
879880

880881
**如何判断是 CPU 密集任务还是 IO 密集任务?**
881882

882-
CPU 密集型简单理解就是利用 CPU 计算能力的任务比如你在内存中对大量数据进行排序。单凡涉及到网络读取,文件读取这类都是 IO 密集型,这类任务的特点是 CPU 计算耗费时间相比于等待 IO 操作完成的时间来说很少,大部分时间都花在了等待 IO 操作完成上。
883+
CPU 密集型简单理解就是利用 CPU 计算能力的任务比如你在内存中对大量数据进行排序。但凡涉及到网络读取,文件读取这类都是 IO 密集型,这类任务的特点是 CPU 计算耗费时间相比于等待 IO 操作完成的时间来说很少,大部分时间都花在了等待 IO 操作完成上。
883884

884885
## 八 参考
885886

docs/java/multi-thread/拿来即用的线程池最佳实践.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88

99
### 为什么要使用线程池?
1010

11-
> **池化技术相比大家已经屡见不鲜了,线程池、数据库连接池、Http 连接池等等都是对这个思想的应用。池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。**
11+
> **池化技术想必大家已经屡见不鲜了,线程池、数据库连接池、Http 连接池等等都是对这个思想的应用。池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。**
1212
1313
**线程池**提供了一种限制和管理资源(包括执行一个任务)。 每个**线程池**还维护一些基本统计信息,例如已完成任务的数量。
1414

1515
这里借用《Java 并发编程的艺术》提到的来说一下**使用线程池的好处**
1616

1717
- **降低资源消耗**。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
18-
- **提高响应速度**。当任务到达时,任务可以不需要的等到线程创建就能立即执行
18+
- **提高响应速度**。当任务到达时,任务可以不需要等到线程创建就能立即执行
1919
- **提高线程的可管理性**。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
2020

2121
### 线程池在实际项目的使用场景
@@ -279,7 +279,7 @@ CPU 密集型简单理解就是利用 CPU 计算能力的任务比如你在内
279279

280280
- **`corePoolSize` :** 核心线程数线程数定义了最小可以同时运行的线程数量。
281281
- **`maximumPoolSize` :** 当队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。
282-
- **`workQueue`:** 当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,信任就会被存放在队列中
282+
- **`workQueue`:** 当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中
283283

284284
**为什么是这三个参数?**
285285

0 commit comments

Comments
 (0)