Skip to content

Commit 238fdcd

Browse files
committed
完善 Thread类 源码内容
1 parent 7892168 commit 238fdcd

1 file changed

Lines changed: 59 additions & 7 deletions

File tree

docs/JDK/Thread.md

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,28 @@ public class Thread implements Runnable {
1010
private int priority;
1111
/** 是否为守护线程 */
1212
private boolean daemon;
13-
/** 目标任务 */
13+
/** 线程要执行的目标任务 */
1414
private Runnable target;
1515
/** 所属线程组 */
1616
private ThreadGroup group;
1717
/** 类加载器 */
1818
private ClassLoader contextClassLoader;
1919
/**
20-
* ThreadLocal设置线程私有变量时 就是通过下面这两个参数完成的,
21-
* ThreadLocal的get/set方法就是通过操作 各个线程的 threadLocals 变量实现的
20+
* ThreadLocal 能为线程设置线程私有变量 就是通过下面这个threadLocals变量完成的,
21+
* ThreadLocal的get/set方法就是通过操作 各个线程的 threadLocals 变量实现的。
22+
* 1、线程A持有一个 ThreadLocalMap 变量;
23+
* 2、线程A调用一个类的 ThreadLocal变量 tlA 的 get/set方法;
24+
* 3、tlA(ThreadLocal)的 get/set方法 获取当前线程A,调用 线程A 的 ThreadLocalMap变量 的get/put方法;
25+
* 4、其它线程 调用 tlA(ThreadLocal)的 get/set方法 同理。
2226
*/
2327
ThreadLocal.ThreadLocalMap threadLocals;
2428
ThreadLocal.ThreadLocalMap inheritableThreadLocals;
2529
/** 线程栈的大小 */
2630
private long stackSize;
27-
/** 线程状态:新建、就绪/运行、阻塞、等待、销毁 */
31+
/**
32+
* Thread类定义了6个线程状态:New、Runnable、Blocked、Waiting、TimedWaiting、Terminated(终止)
33+
* 实际上还会把 Runnable 再细分为 就绪(未抢到时间片) 和 运行中(抢到时间片)
34+
*/
2835
private volatile int threadStatus;
2936
/** 最小优先级 */
3037
public static final int MIN_PRIORITY = 1;
@@ -39,7 +46,7 @@ public class Thread implements Runnable {
3946
* RUNNABLE: 运行,在java多线程模型中,就绪和运行都是运行状态;
4047
* BLOCKED: 阻塞;
4148
* WAITING: 等待,需要其他的线程来唤醒;
42-
* TIMED_WAITING:超时等待,可以在指定的时间内自动醒来;
49+
* TIMED_WAITING:超时等待,可以在指定的时间内自动醒来,如 sleep()方法
4350
* TERMINATED: 终止,线程执行完毕。
4451
*/
4552
public static final class State extends Enum {
@@ -69,8 +76,8 @@ public class Thread implements Runnable {
6976

7077
/**
7178
* 一系列 构造方法 ------------------------------------------------------
72-
* 可以看出来,其中都调用了init()方法,这也是一个约定俗成的规矩, 即,如果要在 new 时进行一些初始化操作,那么请将初始化操作单独写在
73-
* init()方法中,然后在构造函数中调用该 init()方法
79+
* 可以看出来,其中都调用了init()方法,这也是一个约定俗成的规矩, 即,如果要在 new 时进行一些初始化操作,
80+
* 那么请将初始化操作单独写在 init()方法中,然后在构造函数中调用该 init()方法
7481
*/
7582
public Thread() {
7683
daemon = false;
@@ -261,6 +268,51 @@ public class Thread implements Runnable {
261268
}
262269

263270
private native void interrupt0();
271+
272+
/**
273+
* 线程main 调用了线程A的join方法,则 线程main 会被阻塞,直到线程A执行完毕
274+
*/
275+
public final void join() throws InterruptedException {
276+
join(0);
277+
}
278+
279+
/**
280+
* 实际上是利用 wait/notify机制 来实现的
281+
*/
282+
public final synchronized void join(long millis) throws InterruptedException {
283+
long base = System.currentTimeMillis();
284+
long now = 0;
285+
286+
if (millis < 0) {
287+
throw new IllegalArgumentException("timeout value is negative");
288+
}
289+
// millis 为 0,所以走这个分支
290+
if (millis == 0) {
291+
// 当前线程是否还在运行,还在运行 则main线程 进入等待状态,直到 A线程运行完毕,将其唤醒
292+
while (isAlive()) {
293+
wait(0);
294+
}
295+
} else {
296+
while (isAlive()) {
297+
long delay = millis - now;
298+
if (delay <= 0) {
299+
break;
300+
}
301+
wait(delay);
302+
now = System.currentTimeMillis() - base;
303+
}
304+
}
305+
}
306+
307+
/**
308+
* 线程睡眠指定的时间,释放CPU资源,但不释放锁
309+
*/
310+
public static native void sleep(long millis) throws InterruptedException;
311+
312+
/**
313+
* 线程是否还在运行
314+
*/
315+
public final native boolean isAlive();
264316
}
265317
```
266318
之前一直对线程状态 及 状态切换的概念模糊不清,现在通过源码中对线程状态的定义,我们可以画张图来重新回顾一下,以使我们对其有更加深刻的理解。

0 commit comments

Comments
 (0)