1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-06-16 18:10:13 +08:00

Merge pull request #1220 from 2293736867/master

multi-thread/2020最新Java并发进阶常见面试题总结 排版修正
This commit is contained in:
Guide哥 2021-06-03 20:50:15 +08:00 committed by GitHub
commit 07cc257b74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -12,7 +12,7 @@
- [1.3. 构造方法可以使用 synchronized 关键字修饰么?](#13-构造方法可以使用-synchronized-关键字修饰么)
- [1.3. 讲一下 synchronized 关键字的底层原理](#13-讲一下-synchronized-关键字的底层原理)
- [1.3.1. synchronized 同步语句块的情况](#131-synchronized-同步语句块的情况)
- [1.3.2. `synchronized` 修饰方法的的情况](#132-synchronized-修饰方法的的情况)
- [1.3.2. synchronized 修饰方法的的情况](#132-synchronized-修饰方法的的情况)
- [1.3.3.总结](#133总结)
- [1.4. 说说 JDK1.6 之后的 synchronized 关键字底层做了哪些优化,可以详细介绍一下这些优化吗](#14-说说-jdk16-之后的-synchronized-关键字底层做了哪些优化可以详细介绍一下这些优化吗)
- [1.5. 谈谈 synchronized 和 ReentrantLock 的区别](#15-谈谈-synchronized-和-reentrantlock-的区别)
@ -194,7 +194,7 @@ public class SynchronizedDemo {
在执行 `monitorexit` 指令后,将锁计数器设为 0表明锁被释放。如果获取对象锁失败那当前线程就要阻塞等待直到锁被另外一个线程释放为止。
#### 1.3.2. `synchronized` 修饰方法的的情况
#### 1.3.2. synchronized 修饰方法的的情况
```java
public class SynchronizedDemo2 {
@ -381,8 +381,7 @@ Thread Name= 9 formatter = yy-M-d ah:mm
```java
private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
@Override
protected SimpleDateFormat initialValue()
{
protected SimpleDateFormat initialValue(){
return new SimpleDateFormat("yyyyMMdd HHmm");
}
};
@ -394,13 +393,13 @@ Thread Name= 9 formatter = yy-M-d ah:mm
```java
public class Thread implements Runnable {
......
//......
//与此线程有关的ThreadLocal值。由ThreadLocal类维护
ThreadLocal.ThreadLocalMap threadLocals = null;
//与此线程有关的InheritableThreadLocal值。由InheritableThreadLocal类维护
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
......
//......
}
```
@ -428,7 +427,7 @@ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
```java
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
......
//......
}
```
@ -550,8 +549,11 @@ public interface Callable<V> {
> - **CachedThreadPool 和 ScheduledThreadPool** 允许创建的线程数量为 Integer.MAX_VALUE ,可能会创建大量线程,从而导致 OOM。
**方式一:通过构造方法实现**
![ThreadPoolExecutor构造方法](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/ThreadPoolExecutor构造方法.png)
**方式二:通过 Executor 框架的工具类 Executors 来实现**
我们可以创建三种类型的 ThreadPoolExecutor
- **FixedThreadPool** 该方法返回一个固定线程数量的线程池。该线程池中的线程数量始终不变。当有一个新的任务提交时,线程池中若有空闲线程,则立即执行。若没有,则新的任务会被暂存在一个任务队列中,待有线程空闲时,便处理在任务队列中的任务。
@ -559,6 +561,7 @@ public interface Callable<V> {
- **CachedThreadPool** 该方法返回一个可根据实际情况调整线程数量的线程池。线程池的线程数量不确定,但若有空闲线程可以复用,则会优先使用可复用的线程。若所有线程均在工作,又有新的任务提交,则会创建新的线程处理任务。所有线程在当前任务执行完毕后,将返回线程池进行复用。
对应 Executors 工具类中的方法如图所示:
![Executor框架的工具类](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/Executor框架的工具类.png)
### 4.5 ThreadPoolExecutor 类分析
@ -615,8 +618,9 @@ public interface Callable<V> {
如果当前同时运行的线程数量达到最大线程数量并且队列也已经被放满了任时,`ThreadPoolTaskExecutor` 定义一些策略:
- **`ThreadPoolExecutor.AbortPolicy`**:抛出 `RejectedExecutionException`来拒绝新任务的处理。
- **`ThreadPoolExecutor.CallerRunsPolicy`**:调用执行自己的线程运行任务,也就是直接在调用`execute`方法的线程中运行(`run`)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果您的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。
- **`ThreadPoolExecutor.AbortPolicy`** 抛出 `RejectedExecutionException`来拒绝新任务的处理。
- **`ThreadPoolExecutor.CallerRunsPolicy`**
调用执行自己的线程运行任务,也就是直接在调用`execute`方法的线程中运行(`run`)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果您的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。
- **`ThreadPoolExecutor.DiscardPolicy`** 不处理新任务,直接丢弃掉。
- **`ThreadPoolExecutor.DiscardOldestPolicy`** 此策略将丢弃最早的未处理的任务请求。
@ -708,7 +712,6 @@ public class ThreadPoolExecutorDemo {
System.out.println("Finished all threads");
}
}
```
可以看到我们上面的代码指定了:
@ -1037,7 +1040,7 @@ public class CountDownLatchExample1 {
threadPool.execute(() -> {
try {
//处理文件的业务操作
......
//......
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
@ -1051,7 +1054,6 @@ public class CountDownLatchExample1 {
threadPool.shutdown();
System.out.println("finish");
}
}
```
@ -1075,7 +1077,7 @@ CompletableFuture<Void> task6 =
try {
headerFuture.join();
} catch (Exception ex) {
......
//......
}
System.out.println("all done. ");
```