|
5 | 5 | - [线程池](#%E7%BA%BF%E7%A8%8B%E6%B1%A0) |
6 | 6 | - [线程池原理](#%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%8E%9F%E7%90%86) |
7 | 7 | - [线程池大小](#%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%A4%A7%E5%B0%8F) |
| 8 | + - [关闭线程池](#%E5%85%B3%E9%97%AD%E7%BA%BF%E7%A8%8B%E6%B1%A0) |
8 | 9 | - [executor框架](#executor%E6%A1%86%E6%9E%B6) |
9 | 10 | - [简介](#%E7%AE%80%E4%BB%8B) |
10 | 11 | - [ThreadPoolExecutor Demo](#threadpoolexecutor-demo) |
|
49 | 50 | - [并发的条件](#%E5%B9%B6%E5%8F%91%E7%9A%84%E6%9D%A1%E4%BB%B6) |
50 | 51 | - [进程线程](#%E8%BF%9B%E7%A8%8B%E7%BA%BF%E7%A8%8B) |
51 | 52 | - [线程状态](#%E7%BA%BF%E7%A8%8B%E7%8A%B6%E6%80%81) |
| 53 | + - [中断](#%E4%B8%AD%E6%96%AD) |
52 | 54 | - [join/yeild/sleep/wait/park](#joinyeildsleepwaitpark) |
53 | 55 | - [wait()和sleep()的区别](#wait%E5%92%8Csleep%E7%9A%84%E5%8C%BA%E5%88%AB) |
54 | | -- [中断](#%E4%B8%AD%E6%96%AD) |
55 | 56 | - [原子类](#%E5%8E%9F%E5%AD%90%E7%B1%BB) |
56 | 57 | - [基本类型原子类](#%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B%E5%8E%9F%E5%AD%90%E7%B1%BB) |
57 | 58 | - [数组类型原子类](#%E6%95%B0%E7%BB%84%E7%B1%BB%E5%9E%8B%E5%8E%9F%E5%AD%90%E7%B1%BB) |
@@ -141,6 +142,25 @@ CPU 密集型任务(N+1): 这种任务消耗的主要是 CPU 资源,可以 |
141 | 142 |
|
142 | 143 | I/O 密集型任务(2N): 系统会用大部分的时间来处理 I/O 交互,而线程等待 I/O 操作会被阻塞,释放 cpu,这时就可以将 CPU 交出给其它线程使用。因此在 I/O 密集型任务的应用中,我们可以多配置一些线程,具体的计算方法:最佳线程数 = CPU核心数 * (1/CPU利用率) = CPU核心数 * (1 + (I/O耗时/CPU耗时)),一般可设置为2N。 |
143 | 144 |
|
| 145 | +### 关闭线程池 |
| 146 | + |
| 147 | +shutdown(): |
| 148 | + |
| 149 | +将线程池状态置为`SHUTDOWN`,并不会立即停止: |
| 150 | + |
| 151 | +- 停止接收外部提交的任务 |
| 152 | +- 内部正在跑的任务和队列里等待的任务,会执行完 |
| 153 | +- 等到第二步完成后,才真正停止 |
| 154 | + |
| 155 | +shutdownNow(): |
| 156 | + |
| 157 | +将线程池状态置为`STOP`。企图立即停止,事实上不一定: |
| 158 | + |
| 159 | +- 跟shutdown()一样,先停止接收外部提交的任务 |
| 160 | +- 忽略队列里等待的任务 |
| 161 | +- 尝试将正在跑的任务`interrupt`中断(不一定中断成功,取决于任务响应中断的逻辑) |
| 162 | +- 返回未执行的任务列表 |
| 163 | + |
144 | 164 |
|
145 | 165 |
|
146 | 166 | ## executor框架 |
@@ -931,42 +951,7 @@ worker5 finished the task |
931 | 951 |
|
932 | 952 |  |
933 | 953 |
|
934 | | -### join/yeild/sleep/wait/park |
935 | | - |
936 | | -thread.join(),在main中创建了thread线程,在main中调用了thread.join()/thread.join(long millis),main线程放弃cpu控制权,线程进入WAITING/TIMED_WAITING状态,等到thread线程执行完才继续执行main线程。 |
937 | | - |
938 | | -Thread.yield(),一定是当前线程调用此方法,当前线程放弃获取的CPU时间片,但不释放锁资源,由运行状态变为就绪状态,让OS再次选择线程。作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()不会导致阻塞。该方法与sleep()类似,只是不能由用户指定暂停多长时间。 |
939 | | - |
940 | | -Thread.sleep(long millis),一定是当前线程调用此方法,当前线程进入TIMED_WAITING状态,让出cpu资源,但不释放对象锁,指定时间到后又恢复运行。作用:给其它线程执行机会的最佳方式。 |
941 | | - |
942 | | -obj.wait(),当前线程调用对象的wait()方法,当前线程释放对象锁,进入等待队列。依靠notify()/notifyAll()唤醒或者wait(long timeout) timeout时间到自动唤醒。线程需要获取obj对象锁之后才能调用 obj.wait()。 |
943 | | - |
944 | | -obj.notify()唤醒在此对象监视器上等待的单个线程,选择是任意性的。notifyAll()唤醒在此对象监视器上等待的所有线程。 |
945 | | - |
946 | | -LockSupport.park()/LockSupport.parkNanos(long nanos)/LockSupport.parkUntil(long deadlines), 当前线程进入WAITING/TIMED_WAITING状态。对比wait方法,不需要获得锁就可以让线程进入WAITING/TIMED_WAITING状态,需要通过LockSupport.unpark(Thread thread)唤醒。 |
947 | | - |
948 | | - |
949 | | - |
950 | | -### wait()和sleep()的区别 |
951 | | - |
952 | | -相同点: |
953 | | - |
954 | | -1. 使当前线程暂停运行,把机会交给其他线程 |
955 | | -2. 任何线程在等待期间被中断都会抛出InterruptedException |
956 | | - |
957 | | -不同点: |
958 | | - |
959 | | -1. wait() 是Object超类中的方法;而sleep()是线程Thread类中的方法 |
960 | | - |
961 | | -2. 对锁的持有不同,wait()会释放锁,而sleep()并不释放锁 |
962 | | - |
963 | | -3. 唤醒方法不完全相同,wait() 依靠notify或者notifyAll 、中断、达到指定时间来唤醒;而sleep()到达指定时间被唤醒 |
964 | | - |
965 | | -4. 使用位置不同,wait只能在同步代码块或同步控制块中使用,而sleep可以在任何位置使用 |
966 | | - |
967 | | - |
968 | | - |
969 | | -## 中断 |
| 954 | +### 中断 |
970 | 955 |
|
971 | 956 | [线程中断](https://zhuanlan.zhihu.com/p/45667127) |
972 | 957 |
|
@@ -1004,6 +989,37 @@ private static void test2() { |
1004 | 989 | } |
1005 | 990 | ``` |
1006 | 991 |
|
| 992 | +### join/yeild/sleep/wait/park |
| 993 | + |
| 994 | +thread.join(),在main中创建了thread线程,在main中调用了thread.join()/thread.join(long millis),main线程放弃cpu控制权,线程进入WAITING/TIMED_WAITING状态,等到thread线程执行完才继续执行main线程。 |
| 995 | + |
| 996 | +Thread.yield(),一定是当前线程调用此方法,当前线程放弃获取的CPU时间片,但不释放锁资源,由运行状态变为就绪状态,让OS再次选择线程。作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()不会导致阻塞。该方法与sleep()类似,只是不能由用户指定暂停多长时间。 |
| 997 | + |
| 998 | +Thread.sleep(long millis),一定是当前线程调用此方法,当前线程进入TIMED_WAITING状态,让出cpu资源,但不释放对象锁,指定时间到后又恢复运行。作用:给其它线程执行机会的最佳方式。 |
| 999 | + |
| 1000 | +obj.wait(),当前线程调用对象的wait()方法,当前线程释放对象锁,进入等待队列。依靠notify()/notifyAll()唤醒或者wait(long timeout) timeout时间到自动唤醒。线程需要获取obj对象锁之后才能调用 obj.wait()。 |
| 1001 | + |
| 1002 | +obj.notify()唤醒在此对象监视器上等待的单个线程,选择是任意性的。notifyAll()唤醒在此对象监视器上等待的所有线程。 |
| 1003 | + |
| 1004 | +LockSupport.park()/LockSupport.parkNanos(long nanos)/LockSupport.parkUntil(long deadlines), 当前线程进入WAITING/TIMED_WAITING状态。对比wait方法,不需要获得锁就可以让线程进入WAITING/TIMED_WAITING状态,需要通过LockSupport.unpark(Thread thread)唤醒。 |
| 1005 | + |
| 1006 | +### wait()和sleep()的区别 |
| 1007 | + |
| 1008 | +相同点: |
| 1009 | + |
| 1010 | +1. 使当前线程暂停运行,把机会交给其他线程 |
| 1011 | +2. 任何线程在等待期间被中断都会抛出InterruptedException |
| 1012 | + |
| 1013 | +不同点: |
| 1014 | + |
| 1015 | +1. wait() 是Object超类中的方法;而sleep()是线程Thread类中的方法 |
| 1016 | + |
| 1017 | +2. 对锁的持有不同,wait()会释放锁,而sleep()并不释放锁 |
| 1018 | + |
| 1019 | +3. 唤醒方法不完全相同,wait() 依靠notify或者notifyAll 、中断、达到指定时间来唤醒;而sleep()到达指定时间被唤醒 |
| 1020 | + |
| 1021 | +4. 使用位置不同,wait只能在同步代码块或同步控制块中使用,而sleep可以在任何位置使用 |
| 1022 | + |
1007 | 1023 |
|
1008 | 1024 |
|
1009 | 1025 | ## 原子类 |
|
0 commit comments