|
1 | 1 | <!-- GFM-TOC -->
|
2 |
| -* [一、线程状态转换](#一线程状态转换) |
3 |
| - * [新建(New)](#新建new) |
4 |
| - * [可运行(Runnable)](#可运行runnable) |
5 |
| - * [阻塞(Blocked)](#阻塞blocked) |
6 |
| - * [无限期等待(Waiting)](#无限期等待waiting) |
7 |
| - * [限期等待(Timed Waiting)](#限期等待timed-waiting) |
8 |
| - * [死亡(Terminated)](#死亡terminated) |
9 |
| -* [二、使用线程](#二使用线程) |
| 2 | +* [一、使用线程](#一使用线程) |
10 | 3 | * [实现 Runnable 接口](#实现-runnable-接口)
|
11 | 4 | * [实现 Callable 接口](#实现-callable-接口)
|
12 | 5 | * [继承 Thread 类](#继承-thread-类)
|
13 | 6 | * [实现接口 VS 继承 Thread](#实现接口-vs-继承-thread)
|
14 |
| -* [三、基础线程机制](#三基础线程机制) |
| 7 | +* [二、基础线程机制](#二基础线程机制) |
15 | 8 | * [Executor](#executor)
|
16 | 9 | * [Daemon](#daemon)
|
17 | 10 | * [sleep()](#sleep)
|
18 | 11 | * [yield()](#yield)
|
19 |
| -* [四、中断](#四中断) |
| 12 | +* [三、中断](#三中断) |
20 | 13 | * [InterruptedException](#interruptedexception)
|
21 | 14 | * [interrupted()](#interrupted)
|
22 | 15 | * [Executor 的中断操作](#executor-的中断操作)
|
23 |
| -* [五、互斥同步](#五互斥同步) |
| 16 | +* [四、互斥同步](#四互斥同步) |
24 | 17 | * [synchronized](#synchronized)
|
25 | 18 | * [ReentrantLock](#reentrantlock)
|
26 | 19 | * [比较](#比较)
|
27 | 20 | * [使用选择](#使用选择)
|
28 |
| -* [六、线程之间的协作](#六线程之间的协作) |
| 21 | +* [五、线程之间的协作](#五线程之间的协作) |
29 | 22 | * [join()](#join)
|
30 | 23 | * [wait() notify() notifyAll()](#wait-notify-notifyall)
|
31 | 24 | * [await() signal() signalAll()](#await-signal-signalall)
|
| 25 | +* [六、线程状态](#六线程状态) |
| 26 | + * [新建(NEW)](#新建new) |
| 27 | + * [可运行(RUNABLE)](#可运行runable) |
| 28 | + * [阻塞(BLOCKED)](#阻塞blocked) |
| 29 | + * [无限期等待(Waiting)](#无限期等待waiting) |
| 30 | + * [限期等待(Timed Waiting)](#限期等待timed-waiting) |
| 31 | + * [死亡(Terminated)](#死亡terminated) |
32 | 32 | * [七、J.U.C - AQS](#七juc---aqs)
|
33 | 33 | * [CountDownLatch](#countdownlatch)
|
34 | 34 | * [CyclicBarrier](#cyclicbarrier)
|
|
59 | 59 | <!-- GFM-TOC -->
|
60 | 60 |
|
61 | 61 |
|
62 |
| -# 一、线程状态转换 |
63 |
| - |
64 |
| -<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/adfb427d-3b21-40d7-a142-757f4ed73079.png" width="600px"> </div><br> |
65 |
| - |
66 |
| -## 新建(New) |
67 |
| - |
68 |
| -创建后尚未启动。 |
69 |
| - |
70 |
| -## 可运行(Runnable) |
71 | 62 |
|
72 |
| -可能正在运行,也可能正在等待 CPU 时间片。 |
73 |
| - |
74 |
| -包含了操作系统线程状态中的 Running 和 Ready。 |
75 |
| - |
76 |
| -## 阻塞(Blocked) |
77 |
| - |
78 |
| -等待获取一个排它锁,如果其线程释放了锁就会结束此状态。 |
79 |
| - |
80 |
| -## 无限期等待(Waiting) |
81 |
| - |
82 |
| -等待其它线程显式地唤醒,否则不会被分配 CPU 时间片。 |
83 |
| - |
84 |
| -| 进入方法 | 退出方法 | |
85 |
| -| --- | --- | |
86 |
| -| 没有设置 Timeout 参数的 Object.wait() 方法 | Object.notify() / Object.notifyAll() | |
87 |
| -| 没有设置 Timeout 参数的 Thread.join() 方法 | 被调用的线程执行完毕 | |
88 |
| -| LockSupport.park() 方法 | LockSupport.unpark(Thread) | |
89 |
| - |
90 |
| -## 限期等待(Timed Waiting) |
91 |
| - |
92 |
| -无需等待其它线程显式地唤醒,在一定时间之后会被系统自动唤醒。 |
93 |
| - |
94 |
| -调用 Thread.sleep() 方法使线程进入限期等待状态时,常常用“使一个线程睡眠”进行描述。 |
95 |
| - |
96 |
| -调用 Object.wait() 方法使线程进入限期等待或者无限期等待时,常常用“挂起一个线程”进行描述。 |
97 |
| - |
98 |
| -睡眠和挂起是用来描述行为,而阻塞和等待用来描述状态。 |
99 |
| - |
100 |
| -阻塞和等待的区别在于,阻塞是被动的,它是在等待获取一个排它锁。而等待是主动的,通过调用 Thread.sleep() 和 Object.wait() 等方法进入。 |
101 |
| - |
102 |
| -| 进入方法 | 退出方法 | |
103 |
| -| --- | --- | |
104 |
| -| Thread.sleep() 方法 | 时间结束 | |
105 |
| -| 设置了 Timeout 参数的 Object.wait() 方法 | 时间结束 / Object.notify() / Object.notifyAll() | |
106 |
| -| 设置了 Timeout 参数的 Thread.join() 方法 | 时间结束 / 被调用的线程执行完毕 | |
107 |
| -| LockSupport.parkNanos() 方法 | LockSupport.unpark(Thread) | |
108 |
| -| LockSupport.parkUntil() 方法 | LockSupport.unpark(Thread) | |
109 |
| - |
110 |
| -## 死亡(Terminated) |
111 |
| - |
112 |
| -可以是线程结束任务之后自己结束,或者产生了异常而结束。 |
113 |
| - |
114 |
| -# 二、使用线程 |
| 63 | +# 一、使用线程 |
115 | 64 |
|
116 | 65 | 有三种使用线程的方法:
|
117 | 66 |
|
@@ -193,7 +142,7 @@ public static void main(String[] args) {
|
193 | 142 | - Java 不支持多重继承,因此继承了 Thread 类就无法继承其它类,但是可以实现多个接口;
|
194 | 143 | - 类可能只要求可执行就行,继承整个 Thread 类开销过大。
|
195 | 144 |
|
196 |
| -# 三、基础线程机制 |
| 145 | +# 二、基础线程机制 |
197 | 146 |
|
198 | 147 | ## Executor
|
199 | 148 |
|
@@ -258,7 +207,7 @@ public void run() {
|
258 | 207 | }
|
259 | 208 | ```
|
260 | 209 |
|
261 |
| -# 四、中断 |
| 210 | +# 三、中断 |
262 | 211 |
|
263 | 212 | 一个线程执行完毕之后会自动结束,如果在运行过程中发生异常也会提前结束。
|
264 | 213 |
|
@@ -378,7 +327,7 @@ Future<?> future = executorService.submit(() -> {
|
378 | 327 | future.cancel(true);
|
379 | 328 | ```
|
380 | 329 |
|
381 |
| -# 五、互斥同步 |
| 330 | +# 四、互斥同步 |
382 | 331 |
|
383 | 332 | Java 提供了两种锁机制来控制多个线程对共享资源的互斥访问,第一个是 JVM 实现的 synchronized,而另一个是 JDK 实现的 ReentrantLock。
|
384 | 333 |
|
@@ -566,7 +515,7 @@ synchronized 中的锁是非公平的,ReentrantLock 默认情况下也是非
|
566 | 515 |
|
567 | 516 | 除非需要使用 ReentrantLock 的高级功能,否则优先使用 synchronized。这是因为 synchronized 是 JVM 实现的一种锁机制,JVM 原生地支持它,而 ReentrantLock 不是所有的 JDK 版本都支持。并且使用 synchronized 不用担心没有释放锁而导致死锁问题,因为 JVM 会确保锁的释放。
|
568 | 517 |
|
569 |
| -# 六、线程之间的协作 |
| 518 | +# 五、线程之间的协作 |
570 | 519 |
|
571 | 520 | 当多个线程可以一起工作去解决某个问题时,如果某些部分必须在其它部分之前完成,那么就需要对线程进行协调。
|
572 | 521 |
|
@@ -726,6 +675,54 @@ before
|
726 | 675 | after
|
727 | 676 | ```
|
728 | 677 |
|
| 678 | +# 六、线程状态 |
| 679 | + |
| 680 | +一个线程只能处于一种状态,并且这里的线程状态特指 Java 虚拟机的线程状态,不能反映线程在特定操作系统下的状态。 |
| 681 | + |
| 682 | +## 新建(NEW) |
| 683 | + |
| 684 | +创建后尚未启动。 |
| 685 | + |
| 686 | +## 可运行(RUNABLE) |
| 687 | + |
| 688 | +正在 Java 虚拟机中运行。但是在操作系统层面,它可能处于运行状态,也可能等待资源调度(例如处理器资源),资源调度完成就进入运行状态。所以该状态的可运行是指可以被运行,具体有没有运行要看底层操作系统的资源调度。 |
| 689 | + |
| 690 | +## 阻塞(BLOCKED) |
| 691 | + |
| 692 | +请求获取 monitor lock 从而进入 synchronized 函数或者代码块,但是其它线程已经占用了该 monitor lock,所以出于阻塞状态。要结束该状态进入从而 RUNABLE 需要其他线程释放 monitor lock。 |
| 693 | + |
| 694 | +## 无限期等待(Waiting) |
| 695 | + |
| 696 | +等待其它线程显式地唤醒。 |
| 697 | + |
| 698 | +阻塞和等待的区别在于,阻塞是被动的,它是在等待获取 monitor lock。而等待是主动的,通过调用 Object.wait() 等方法进入。 |
| 699 | + |
| 700 | +| 进入方法 | 退出方法 | |
| 701 | +| --- | --- | |
| 702 | +| 没有设置 Timeout 参数的 Object.wait() 方法 | Object.notify() / Object.notifyAll() | |
| 703 | +| 没有设置 Timeout 参数的 Thread.join() 方法 | 被调用的线程执行完毕 | |
| 704 | +| LockSupport.park() 方法 | LockSupport.unpark(Thread) | |
| 705 | + |
| 706 | +## 限期等待(Timed Waiting) |
| 707 | + |
| 708 | +无需等待其它线程显式地唤醒,在一定时间之后会被系统自动唤醒。 |
| 709 | + |
| 710 | +| 进入方法 | 退出方法 | |
| 711 | +| --- | --- | |
| 712 | +| Thread.sleep() 方法 | 时间结束 | |
| 713 | +| 设置了 Timeout 参数的 Object.wait() 方法 | 时间结束 / Object.notify() / Object.notifyAll() | |
| 714 | +| 设置了 Timeout 参数的 Thread.join() 方法 | 时间结束 / 被调用的线程执行完毕 | |
| 715 | +| LockSupport.parkNanos() 方法 | LockSupport.unpark(Thread) | |
| 716 | +| LockSupport.parkUntil() 方法 | LockSupport.unpark(Thread) | |
| 717 | + |
| 718 | +调用 Thread.sleep() 方法使线程进入限期等待状态时,常常用“使一个线程睡眠”进行描述。调用 Object.wait() 方法使线程进入限期等待或者无限期等待时,常常用“挂起一个线程”进行描述。睡眠和挂起是用来描述行为,而阻塞和等待用来描述状态。 |
| 719 | + |
| 720 | +## 死亡(Terminated) |
| 721 | + |
| 722 | +可以是线程结束任务之后自己结束,或者产生了异常而结束。 |
| 723 | + |
| 724 | +[Java SE 9 Enum Thread.State](https://docs.oracle.com/javase/9/docs/api/java/lang/Thread.State.html) |
| 725 | + |
729 | 726 | # 七、J.U.C - AQS
|
730 | 727 |
|
731 | 728 | java.util.concurrent(J.U.C)大大提高了并发性能,AQS 被认为是 J.U.C 的核心。
|
|
0 commit comments