Skip to content

Commit 4ca29f1

Browse files
committed
修正生产者/消费者模式文章中的编辑错误
1 parent bee2f33 commit 4ca29f1

File tree

1 file changed

+15
-13
lines changed

1 file changed

+15
-13
lines changed

java/concurrence/producer-consumer.md

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,22 @@
44

55
Object类中相关的方法有notify方法和wait方法。因为wait和notify方法定义在Object类中,因此会被所有的类所继承。这些方法都是**final**的,即它们都是不能被重写的,不能通过子类覆写去改变它们的行为。
66

7-
**①wait\(\)方法:**让当前线程进入等待,并释放锁。
7+
**①wait\(\)方法:** 让当前线程进入等待,并释放锁。
88

9-
**②wait\(long\)方法:**让当前线程进入等待,并释放锁,不过等待时间为long,超过这个时间没有对当前线程进行唤醒,将自动唤醒
9+
**②wait\(long\)方法:** 让当前线程进入等待,并释放锁,不过等待时间为long,超过这个时间没有对当前线程进行唤醒,**自动唤醒**
1010

11-
**③notify\(\)方法:**让当前线程通知那些处于等待状态的线程,当前线程执行完毕后释放锁,并从其他线程中唤醒其中一个继续执行。
11+
**③notify\(\)方法:** 让当前线程通知那些处于等待状态的线程,当前线程执行完毕后释放锁,并从其他线程中唤醒其中一个继续执行。
1212

13-
**④notifyAll\(\)方法:**让当前线程通知那些处于等待状态的线程,当前线程执行完毕后释放锁,将唤醒所有等待状态的线程。
13+
**④notifyAll\(\)方法:** 让当前线程通知那些处于等待状态的线程,当前线程执行完毕后释放锁,将唤醒所有等待状态的线程。
1414

1515
##### wait\(\)方法使用注意事项
1616

1717
①当前的线程必须拥有当前对象的monitor,也即lock,就是锁,才能调用wait\(\)方法,否则将抛出异常java.lang.IllegalMonitorStateException。
1818

1919
②线程调用wait\(\)方法,释放它对锁的拥有权,然后等待另外的线程来通知它(通知的方式是notify\(\)或者notifyAll\(\)方法),这样它才能重新获得锁的拥有权和恢复执行。
2020

21-
③要确保调用wait\(\)方法的时候拥有锁,即,wait\(\)方法的调用必须放在synchronized方法或synchronized块中。
21+
③要确保调用wait\(\)方法的时候拥有锁,即,wait\(\)方法的调用必须放在synchronized方法或synchronized块中。
22+
2223
**wait\(\)与sleep\(\)比较**
2324

2425
当线程调用了wait\(\)方法时,它会释放掉对象的锁。
@@ -135,7 +136,7 @@ public class Subtract {
135136
}
136137
```
137138

138-
**线程ThreadAdd **
139+
**线程ThreadAdd**
139140

140141
```java
141142
public class ThreadAdd extends Thread{
@@ -153,7 +154,7 @@ public class ThreadAdd extends Thread{
153154
}
154155
```
155156

156-
**线程ThreadSubtract **
157+
**线程ThreadSubtract**
157158

158159
```java
159160
public class ThreadSubtract extends Thread{
@@ -171,7 +172,7 @@ public class ThreadSubtract extends Thread{
171172
}
172173
```
173174

174-
**先开启两个ThreadSubtract线程,由于list中没有元素,进入等待状态。再开启一个ThreadAdd线程,向list中增加一个元素,然后唤醒两个ThreadSubtract线程**
175+
**先开启两个ThreadSubtract线程,由于list中没有元素,进入等待状态。再开启一个ThreadAdd线程,向list中增加一个元素,然后唤醒两个ThreadSubtract线程**
175176

176177
```java
177178
public static void main(String[] args) throws InterruptedException {
@@ -388,13 +389,13 @@ Condition方式实现类似,篇幅有限不全部贴出来。
388389

389390
##### 2.多生产与多消费
390391

391-
**特殊情况:**按照上述一生产与一消费的情况,通过创建多个生产者和消费者线程,实现多生产与多消费的情况,将会出现“假死”。
392+
**特殊情况:** 按照上述一生产与一消费的情况,通过创建多个生产者和消费者线程,实现多生产与多消费的情况,将会出现“假死”。
392393

393-
**具体原因:**多个生产者和消费者线程。当全部运行后,生产者线程生产数据后,可能唤醒的同类即生产者线程。此时可能会出现如下情况:所有生产者线程进入等待状态,然后消费者线程消费完数据后,再次唤醒的还是消费者线程,直至所有消费者线程都进入等待状态,此时将进入“假死”。
394+
**具体原因:** 多个生产者和消费者线程。当全部运行后,生产者线程生产数据后,可能唤醒的同类即生产者线程。此时可能会出现如下情况:所有生产者线程进入等待状态,然后消费者线程消费完数据后,再次唤醒的还是消费者线程,直至所有消费者线程都进入等待状态,此时将进入“假死”。
394395

395-
**解决方法:**将notify\(\)或signal\(\)方法改为notifyAll\(\)或signalAll\(\)方法,这样就不怕因为唤醒同类而进入“假死”状态了。
396+
**解决方法:** 将notify\(\)或signal\(\)方法改为notifyAll\(\)或signalAll\(\)方法,这样就不怕因为唤醒同类而进入“假死”状态了。
396397

397-
**Condition方式实现**
398+
**Condition方式实现**
398399
生产者
399400

400401
```java
@@ -489,7 +490,8 @@ public static void main(String[] args) throws InterruptedException {
489490
> set的值是:148827212374628960540810047
490491
> get的值是:148827212374628960540810047
491492
492-
可见交替地进行get/set实现多生产/多消费模式。
493+
可见交替地进行get/set实现多生产/多消费模式。
494+
493495
**注意:相比一生产一消费的模式,改动了两处。①signal\(\)-->signalAll\(\)避免进入“假死”状态。②if\(\)判断-->while\(\)循环,重新判断条件,避免逻辑混乱。**
494496

495497
以上就是Java线程间通信的相关知识,以生产者/消费者模式为例,讲解线程间通信的使用以及注意事项。

0 commit comments

Comments
 (0)