Skip to content

Commit

Permalink
java并发面试题补充
Browse files Browse the repository at this point in the history
  • Loading branch information
TysonDai committed Apr 26, 2023
1 parent e100269 commit 67ec3c3
Show file tree
Hide file tree
Showing 8 changed files with 7,960 additions and 53 deletions.
2 changes: 1 addition & 1 deletion docs/advance/system-design/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@

**扫描以下二维码**领取50元的优惠券即可加入。星球定价**148**元,减去**50**元的优惠券,等于说只需要98元的价格就可以加入,服务期一年,**每天不到三毛钱**(0.26元),相比培训班几万块的学费,非常值了,星球提供的服务可以说**远超**门票价格了。

![](http://img.topjavaer.cn/img/星球优惠券.png)
![](http://img.topjavaer.cn/img/202304212233017.png)
2 changes: 1 addition & 1 deletion docs/computer-basic/network.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ head:

**扫描以下二维码**领取50元的优惠券即可加入。星球定价**148**元,减去**50**元的优惠券,等于说只需要**98**元的价格就可以加入,服务期一年,**每天不到三毛钱**(0.26元),相比培训班几万块的学费,非常值了,星球提供的服务可以说**远超**门票价格了。

![](http://img.topjavaer.cn/img/星球优惠券.png)
![](http://img.topjavaer.cn/img/202304212233017.png)
2 changes: 1 addition & 1 deletion docs/java/java-basic.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ head:
>
> **扫描以下二维码**领取50元的优惠券即可加入。星球定价**148**元,减去**50**元的优惠券,等于说只需要**98**元的价格就可以加入,服务期一年,**每天不到三毛钱**(0.26元),相比培训班几万块的学费,非常划算了,星球提供的服务可以说**远超**门票价格了。
>
> ![](http://img.topjavaer.cn/img/星球优惠券.png)
> ![前面内容](http://img.topjavaer.cn/img/202304212238005.png)首页
## Java的特点

Expand Down
64 changes: 30 additions & 34 deletions docs/java/java-concurrent.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ head:
>
> [大彬的学习圈](https://topjavaer.cn/zsxq/introduce.html)**加入方式**
>
> ![](http://img.topjavaer.cn/img/星球优惠券.png)
> ![前面内容](http://img.topjavaer.cn/img/202304212238005.png)
## 线程池

Expand Down Expand Up @@ -214,7 +214,33 @@ public static ExecutorService newCachedThreadPool() {

适用场景:周期性执行任务的场景,需要限制线程数量的场景。

### 怎么判断线程池的任务是不是执行完了?

有几种方法:

1、使用线程池的原生函数**isTerminated()**;

executor提供一个原生函数isTerminated()来判断线程池中的任务是否全部完成。如果全部完成返回true,否则返回false。

2、**使用重入锁,维持一个公共计数**

所有的普通任务维持一个计数器,当任务完成时计数器加一(这里要加锁),当计数器的值等于任务数时,这时所有的任务已经执行完毕了。

3、**使用CountDownLatch**

它的原理跟第二种方法类似,给CountDownLatch一个计数值,任务执行完毕后,调用countDown()执行计数值减一。最后执行的任务在调用方法的开始调用await()方法,这样整个任务会阻塞,直到这个计数值为零,才会继续执行。

这种方式的**缺点**就是需要提前知道任务的数量。

4、**submit向线程池提交任务,使用Future判断任务执行状态**

使用submit向线程池提交任务与execute提交不同,submit会有Future类型的返回值。通过future.isDone()方法可以知道任务是否执行完成。

### 为什么要使用Executor线程池框架呢?

- 每次执行任务都通过new Thread()去创建线程,比较消耗性能,创建一个线程是比较耗时、耗资源的
- 调用new Thread()创建的线程缺乏管理,可以无限制的创建,线程之间的相互竞争会导致过多占用系统资源而导致系统瘫痪
- 直接使用new Thread()启动的线程不利于扩展,比如定时执行、定期执行、定时定期执行、线程中断等都不好实现

## 进程线程

Expand Down Expand Up @@ -528,7 +554,10 @@ interrupt() 并不能真正的中断线程,需要被调用的线程自己进

使线程转到阻塞状态。millis参数设定睡眠的时间,以毫秒为单位。当睡眠结束后,线程自动转为Runnable状态。

### 如何停止一个正在运行的线程?

1. 使用共享变量的方式。共享变量可以被多个执行相同任务的线程用来作为是否停止的信号,通知停止线程的执行。
2. 使用interrupt方法终止线程。当一个线程被阻塞,处于不可运行状态时,即使主程序中将该线程的共享变量设置为true,但该线程此时根本无法检查循环标志,当然也就无法立即中断。这时候可以使用Thread提供的interrupt()方法,因为该方法虽然不会中断一个正在运行的线程,但是它可以使一个被阻塞的线程抛出一个中断异常,从而使线程提前结束阻塞状态。

## volatile底层原理

Expand Down Expand Up @@ -1177,17 +1206,6 @@ public final void lazySet(int i, int newValue)//最终 将index=i 位置的元
- AtomicStampedReference:带有版本号的引用类型原子类。该类将整数值与引用关联起来,可用于解决原子的更新数据和数据的版本号,可以解决使用 CAS 进行原子更新时可能出现的 ABA 问题。
- AtomicMarkableReference :原子更新带有标记的引用类型。该类将 boolean 标记与引用关联起来

## 为什么要使用Executor线程池框架呢?

- 每次执行任务都通过new Thread()去创建线程,比较消耗性能,创建一个线程是比较耗时、耗资源的
- 调用new Thread()创建的线程缺乏管理,可以无限制的创建,线程之间的相互竞争会导致过多占用系统资源而导致系统瘫痪
- 直接使用new Thread()启动的线程不利于扩展,比如定时执行、定期执行、定时定期执行、线程中断等都不好实现

## 如何停止一个正在运行的线程?

1. 使用共享变量的方式。共享变量可以被多个执行相同任务的线程用来作为是否停止的信号,通知停止线程的执行。
2. 使用interrupt方法终止线程。当一个线程被阻塞,处于不可运行状态时,即使主程序中将该线程的共享变量设置为true,但该线程此时根本无法检查循环标志,当然也就无法立即中断。这时候可以使用Thread提供的interrupt()方法,因为该方法虽然不会中断一个正在运行的线程,但是它可以使一个被阻塞的线程抛出一个中断异常,从而使线程提前结束阻塞状态。

## 什么是Daemon线程?

后台(daemon)线程,是指在程序运行的时候在后台提供一种通用服务的线程,并且这个线程并不属于程序中不可或缺的部分。因此,当所有的非后台线程结束时,程序也就终止了,同时会杀死进程中的所有后台线程。反过来说,只要有任何非后台线程还在运行,程序就不会终止。必须在线程启动之前调用setDaemon()方法,才能把它设置为后台线程。
Expand All @@ -1203,28 +1221,6 @@ SynchronizedMap一次锁住整张表来保证线程安全,所以每次只能
JDK1.8 ConcurrentHashMap采用CAS和synchronized来保证并发安全。数据结构采用数组+链表/红黑二叉树。synchronized只锁定当前链表或红黑二叉树的首节点,支持并发访问、修改。
另外ConcurrentHashMap使用了一种不同的迭代方式。当iterator被创建后集合再发生改变就不再是抛出ConcurrentModificationException,取而代之的是在改变时new新的数据从而不影响原有的数据 ,iterator完成后再将头指针替换为新的数据 ,这样iterator线程可以使用原来老的数据,而写线程也可以并发的完成改变。

## 怎么判断线程池的任务是不是执行完了?

有几种方法:

1、使用线程池的原生函数**isTerminated()**;

executor提供一个原生函数isTerminated()来判断线程池中的任务是否全部完成。如果全部完成返回true,否则返回false。

2、**使用重入锁,维持一个公共计数**

所有的普通任务维持一个计数器,当任务完成时计数器加一(这里要加锁),当计数器的值等于任务数时,这时所有的任务已经执行完毕了。

3、**使用CountDownLatch**

它的原理跟第二种方法类似,给CountDownLatch一个计数值,任务执行完毕后,调用countDown()执行计数值减一。最后执行的任务在调用方法的开始调用await()方法,这样整个任务会阻塞,直到这个计数值为零,才会继续执行。

这种方式的**缺点**就是需要提前知道任务的数量。

4、**submit向线程池提交任务,使用Future判断任务执行状态**

使用submit向线程池提交任务与execute提交不同,submit会有Future类型的返回值。通过future.isDone()方法可以知道任务是否执行完成。

## 什么是Future?

在并发编程中,不管是继承thread类还是实现runnable接口,都无法保证获取到之前的执行结果。通过实现Callback接口,并用Future可以来接收多线程的执行结果。
Expand Down
2 changes: 1 addition & 1 deletion docs/java/jvm.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@

**扫描以下二维码**领取50元的优惠券即可加入。星球定价**148**元,减去**50**元的优惠券,等于说只需要**98**元的价格就可以加入,服务期一年,**每天不到三毛钱**(0.26元),相比培训班几万块的学费,非常值了,星球提供的服务可以说**远超**门票价格了。

![](http://img.topjavaer.cn/img/星球优惠券.png)
![](http://img.topjavaer.cn/img/202304212233017.png)
2 changes: 1 addition & 1 deletion docs/system-design/2-order-timeout-auto-cancel.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ sidebar: heading

6、打卡学习,**大学自习室的氛围**,一起蜕变成长

![](http://img.topjavaer.cn/img/星球优惠券-学习网站.png)
![前面内容](http://img.topjavaer.cn/img/202304212238005.png)

--分割线--

Expand Down
2 changes: 1 addition & 1 deletion docs/zsxq/introduce.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,4 @@ APP端页面如下(建议大家**使用APP**,因为APP布局更加美观,

PS:如果加入学习圈之后觉得不合适,**支持3天内全额退款**~

![](http://img.topjavaer.cn/img/星球优惠券-学习网站.png)
![](http://img.topjavaer.cn/img/202304212238396.png)
Loading

0 comments on commit 67ec3c3

Please sign in to comment.