|
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