Skip to content

Commit 25e1428

Browse files
committed
✏️ Fixing typos.
1 parent 6c4c8fa commit 25e1428

File tree

3 files changed

+74
-11
lines changed

3 files changed

+74
-11
lines changed

MD/concurrent/thread-communication.md

+71-8
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,28 @@ public class TwoThreadWaitNotify {
110110
}
111111
```
112112

113+
输出结果:
114+
115+
```
116+
t2+-+奇数93
117+
t1+-+偶数94
118+
t2+-+奇数95
119+
t1+-+偶数96
120+
t2+-+奇数97
121+
t1+-+偶数98
122+
t2+-+奇数99
123+
t1+-+偶数100
124+
```
125+
113126
这里的线程 A 和线程 B 都对同一个对象 `TwoThreadWaitNotify.class` 获取锁,A 线程调用了同步对象的 wait() 方法释放了锁并进入 `WAITING` 状态。
114127

115-
B 线程调用了 notify() 方法,这样 A 线程收到通知之后就可以从 wait() 方法中返回。利用了 `TwoThreadWaitNotify.class` 对象完成了交互。
128+
B 线程调用了 notify() 方法,这样 A 线程收到通知之后就可以从 wait() 方法中返回。
116129

117-
这里有一些注意点:
130+
这里利用了 `TwoThreadWaitNotify.class` 对象完成了通信。
118131

119-
- wait() 、nofify() 、nofityAll() 调用的前提都是获得了对象的锁(也可成为对象监视器)。
132+
有一些需要注意:
133+
134+
- wait() 、nofify() 、nofityAll() 调用的前提都是获得了对象的锁(也可称为对象监视器)。
120135
- 调用 wait() 方法后线程会释放锁,进入 `WAITING` 状态,该线程也会被移动到**等待队列**中。
121136
- 调用 notify() 方法会将**等待队列**中的线程移动到**同步队列**中,线程状态也会更新为 `BLOCKED`
122137
- 从 wait() 方法返回的前提是调用 notify() 方法的线程释放锁,wait() 方法的线程获得锁。
@@ -196,6 +211,15 @@ synchronized(Object){
196211
}
197212
```
198213

214+
输出结果:
215+
216+
```
217+
2018-03-16 20:21:30.967 [Thread-1] INFO c.c.actual.ThreadCommunication - running2
218+
2018-03-16 20:21:30.967 [Thread-0] INFO c.c.actual.ThreadCommunication - running
219+
2018-03-16 20:21:34.972 [main] INFO c.c.actual.ThreadCommunication - main over
220+
221+
```
222+
199223
`t1.join()` 时会一直阻塞到 t1 执行完毕,所以最终主线程会等待 t1 和 t2 线程执行完毕。
200224

201225
其实从源码可以看出,join() 也是利用的等待通知机制:
@@ -212,7 +236,7 @@ synchronized(Object){
212236

213237
## volatile 共享内存
214238

215-
因为 Java 其实是采用共享内存的方式进行线程通信的,所以可以采用以下方式用主线程关闭 A 线程:
239+
因为 Java 是采用共享内存的方式进行线程通信的,所以可以采用以下方式用主线程关闭 A 线程:
216240

217241
```java
218242
public class Volatile implements Runnable{
@@ -246,9 +270,18 @@ public class Volatile implements Runnable{
246270
}
247271
```
248272

273+
输出结果:
274+
```
275+
thread A正在运行。。。
276+
thread A正在运行。。。
277+
thread A正在运行。。。
278+
thread A正在运行。。。
279+
thread A执行完毕
280+
```
281+
249282
这里的 flag 存放于主内存中,所以主线程和线程 A 都可以看到。
250283

251-
flag 采用 volatile 修饰主要是为了内存可见性,具体内容可以查看[这里](http://crossoverjie.top/2018/03/09/volatile/)
284+
flag 采用 volatile 修饰主要是为了内存可见性,更多内容可以查看[这里](http://crossoverjie.top/2018/03/09/volatile/)
252285

253286

254287
## CountDownLatch 并发工具
@@ -283,11 +316,23 @@ CountDownLatch 可以实现 join 相同的功能,但是更加的灵活。
283316
}
284317
```
285318

319+
输出结果:
320+
321+
```
322+
2018-03-16 20:19:44.126 [Thread-0] INFO c.c.actual.ThreadCommunication - thread run
323+
2018-03-16 20:19:44.126 [Thread-2] INFO c.c.actual.ThreadCommunication - thread run
324+
2018-03-16 20:19:44.126 [Thread-1] INFO c.c.actual.ThreadCommunication - thread run
325+
2018-03-16 20:19:46.136 [Thread-2] INFO c.c.actual.ThreadCommunication - thread end
326+
2018-03-16 20:19:46.136 [Thread-1] INFO c.c.actual.ThreadCommunication - thread end
327+
2018-03-16 20:19:46.136 [Thread-0] INFO c.c.actual.ThreadCommunication - thread end
328+
2018-03-16 20:19:46.136 [main] INFO c.c.actual.ThreadCommunication - main over total time=2012
329+
```
330+
286331
CountDownLatch 也是基于 AQS(AbstractQueuedSynchronizer) 实现的,更多实现参考 [ReentrantLock 实现原理](http://crossoverjie.top/2018/01/25/ReentrantLock/)
287332

288333
- 初始化一个 CountDownLatch 时告诉并发的线程,然后在每个线程处理完毕之后调用 countDown() 方法。
289334
- 该方法会将 AQS 内置的一个 state 状态 -1 。
290-
- 最终在主线程调用 await() 方法,它会知道 `state == 0` 的时候返回。
335+
- 最终在主线程调用 await() 方法,它会阻塞直到 `state == 0` 的时候返回。
291336

292337
## 线程响应中断
293338

@@ -319,11 +364,19 @@ public class StopThread implements Runnable {
319364
}
320365
```
321366

367+
输出结果:
368+
369+
```
370+
thread A运行中。。
371+
thread A运行中。。
372+
thread A退出。。
373+
```
374+
322375
可以采用中断线程的方式来通信,调用了 `thread.interrupt()` 方法其实就是将 thread 中的一个标志属性置为了 true。
323376

324-
并不是说调用了该方法就可以中断线程,如果不对这个标志进行响应其实是没有什么作用的(这里对这个标志进行了判断)。
377+
并不是说调用了该方法就可以中断线程,如果不对这个标志进行响应其实是没有什么作用(这里对这个标志进行了判断)。
325378

326-
但是如果抛出了 InterruptedException 异常,该标志就会被 JVM 重置为 false。
379+
**但是如果抛出了 InterruptedException 异常,该标志就会被 JVM 重置为 false。**
327380

328381
## 线程池 awaitTermination() 方法
329382

@@ -364,6 +417,16 @@ public class StopThread implements Runnable {
364417
}
365418
```
366419

420+
输出结果:
421+
422+
```
423+
2018-03-16 20:18:01.273 [pool-1-thread-2] INFO c.c.actual.ThreadCommunication - running2
424+
2018-03-16 20:18:01.273 [pool-1-thread-1] INFO c.c.actual.ThreadCommunication - running
425+
2018-03-16 20:18:02.273 [main] INFO c.c.actual.ThreadCommunication - 线程还在执行。。。
426+
2018-03-16 20:18:03.278 [main] INFO c.c.actual.ThreadCommunication - 线程还在执行。。。
427+
2018-03-16 20:18:04.278 [main] INFO c.c.actual.ThreadCommunication - main over
428+
```
429+
367430
使用这个 `awaitTermination()` 方法的前提需要关闭线程池,如调用了 `shutdown()` 方法。
368431

369432
调用了 `shutdown()` 之后线程池会停止接受新任务,并且会平滑的关闭线程池中现有的任务。

src/main/java/com/crossoverjie/actual/ThreadCommunication.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ public class ThreadCommunication {
2020
private final static Logger LOGGER = LoggerFactory.getLogger(ThreadCommunication.class);
2121

2222
public static void main(String[] args) throws Exception {
23-
//join();
23+
join();
2424
//executorService();
2525
//countDownLatch();
26-
piped();
26+
//piped();
2727

2828
}
2929

src/main/java/com/crossoverjie/concurrent/StopThread.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import java.util.concurrent.TimeUnit;
44

55
/**
6-
* Function:
6+
* Function:响应中断
77
*
88
* @author crossoverJie
99
* Date: 16/03/2018 01:41

0 commit comments

Comments
 (0)