@@ -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
218242public 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+
286331CountDownLatch 也是基于 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() ` 之后线程池会停止接受新任务,并且会平滑的关闭线程池中现有的任务。
0 commit comments