源码:java.lang.Thread 源码解析

1. TODO


2. 脑图

  1. Xmind

  2. Edraw

  3. Hexo 地址
    👉 http://blog.wangjia.ink/2025/11/12/源码:java.lang.Thread源码解析/


3. 基础部分

3.1. Thread 概述

Thread 是一个具体类,实现了 java.util.concurrent.Runnable

Thread 实例是一个 Runnable 任务,当我们调用 Thread#start 后,JVM 会在操作系统层面请求创建一个本地线程。一旦操作系统创建了这个本地线程,并将其与 Thread 实例 “绑定”,Thread 实例就会进入可运行状态。当本地线程被分配到 CPU 时间片后,开始执行 Java 代码,执行的就是 Thread#run

然而,由于 Thread#run 的源码又是:

1
2
3
4
5
6
7
public void run() {

if (target != null) {
target.run();
}

}

所以线程执行的流程大致为:本地线程 ➔ Thread#run ➔ target#run

[!NOTE] 注意事项

  1. 详见源码:Runnable
    1. obsidian 内部链接:
      1. 源码:java.util.concurrent.Runnable源码解析
    2. Hexo 链接:
      1. http://blog.wangjia.ink/2025/09/02/%E6%BA%90%E7%A0%81%EF%BC%9Ajava.util.concurrent.Runnable%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/
  2. 虽然线程执行的流程大致为:本地线程 ➔ Thread#run ➔ target#run。但是在某些场景下,我们不希望在创建 Thread 实例时传入一个 Runnable 实例,因为我们已经明确知道该线程要执行的具体逻辑。此时,常见的做法是直接继承 Thread 具体类,并重写 Thread#run,我们直接使用这个 Thread 具体类的子类。这样线程执行的流程大致为:本地线程 ➔ Thread#run
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MyThread extends Thread{  

@Override
public void run() {
...
}

}


public class Test {

public static void main(String[] args) {
Thread myThread = new MyThread();
myThread.start();
}

}

3.2. 创建 Thread 实例常见方式

3.2.1. 继承 Thread 具体类,重写 Thread#run,创建 Thread 具体类的子类实例

正如我们上面讨论的,直接继承 Thread 类,重写 Thread#run,创建 Thread 具体类的子类实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MyThread extends Thread{  

@Override
public void run() {
...
}

}


public class Test {

public static void main(String[] args) {
Thread myThread = new MyThread();
myThread.start();
}

}

[!NOTE] 注意事项

  1. 我们可以使用匿名内部类继承 Thread 具体类:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Test {  

public static void main(String[] args) {
Thread myThread = new Thread("myThread") {
@Override
public void run() {
...
}
};
myThread.start();
}

}

3.2.2. 创建 Runnable 实例,创建 Thread 实例,并将 Runnable 实例作为 Thread 实例的构造方法参数传递进去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Test {  

public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
....
}
};
Thread myThread = new Thread(runnable, "myThread");
myThread.start();
}

}

3.2.3. 使用线程池

详见笔记:JUC

  1. obsidian 内部链接
    1. 笔记:JUC
  2. Hexo 链接
    1. http://blog.wangjia.ink/2025/11/23/笔记:JUC/

4. 构造方法

4.1. Thread(String name)

1
2
3
4
5
public Thread(String name) {

this(null, null, name, 0);

}

4.2. Thread(Runnable target)

1
2
3
4
5
public Thread(Runnable target) {

this(null, target, "Thread-" + nextThreadNum(), 0);

}

4.3. Thread(Runnable target, String name)

1
2
3
4
5
public Thread(Runnable target, String name) {

this(null, target, name, 0);

}

4.4. Thread(ThreadGroup group, Runnable target, String name, long stackSize)

1
2
3
4
5
6
public Thread(ThreadGroup group, Runnable target, String name,
long stackSize) {

this(group, target, name, stackSize, null, true);

}

[!NOTE] 注意事项

  1. ThreadGroup 是一个非常古老且很少被正确使用的功能,在现代开发中几乎永远不会碰它

5. 实例方法

5.1. 实例具体方法

5.1.1. 具体方法(普通)

5.1.1.1. void start()

该方法用于非阻塞启动一个 Thread 实例

当我们调用 Thread#start 后,JVM 会在操作系统层面请求创建一个本地线程。一旦操作系统创建了这个本地线程,并将其与 Thread 实例 “绑定”,Thread 实例就会进入可运行状态

当本地线程被分配到 CPU 时间片后,开始执行 Java 代码,执行的就是 Thread#run

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* ============================================
* 实例具体方法(普通):
* public synchronized void start()
* --------------------------------------------
* 1. 访问修饰符
* 1. public
* 1. 天下皆公(EveryWhere)
*
* 2. 非访问修饰符
* 1. synchronized
* 1. 方法加 synchronized 锁
*
* 3. 方法参数
*
* 4. 返回值
*
* 5. 抛出异常
* 1. IllegalThreadStateException
* 1. 如果 Thread 实例已启动,但是又被启动,就会抛出 IllegalThreadStateException 异常
* 2. 简单来说就是:一个 Thread 实例只能调用一次 Thread#start
*
* 6. 使用示例
* Thread myThread = new Thread("myThread") {
* @Override
* public void run() {
* ...
* }
* };
*
* myThread.start();
* ============================================
*/
public synchronized void start() {

if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
}
}

}

5.1.1.2. void interrupt()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 用于非阻塞中断线程
//
// 该方法会为被中断的 Thread 实例设置中断状态
//
// 如果被中断的 Thread 实例处于 RUNNABLE 状态,就只会设置 Thread 实例的中断状态
//
// 如果被中断的 Thread 实例处于 BLOCKED、WAITING、TIMED_WAITING 状态,可能有以下几种情况:
// 1. 本地线程进入阻塞状态,Thread 实例进入 BWTW 状态后,能响应中断。线程被唤醒,重新获得 CPU 时间片后,会抛出 InterruptedException 受检异常,并清除 Thread 实例的中断状态(异常退出或正常退出(发生异常),要看我们是否对该异常进行捕获并处理)
// 2. 本地线程进入阻塞状态,Thread 实例进入 BWTW 状态后,能响应中断。线程被唤醒,重新获得 CPU 时间片后,不会抛出 InterruptedException 受检异常,但会保留 Thread 实例的中断状态,继续向下执行(正常退出(未发生异常))
// 3. 本地线程进入阻塞状态,Thread 实例进入 BWTW 状态后,不能能响应中断。线程会继续阻塞,并会保留 Thread 示例的中断状态。当线程被唤醒后,会继续向下执行(正常退出(未发生异常))
public void interrupt() {

if (this != Thread.currentThread()) {
checkAccess();

synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupted = true;
interrupt0();
b.interrupt(this);
return;
}
}
}
interrupted = true;
interrupt0();

}

5.1.1.3. void setPriority(int newPriority)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 用于非阻塞设置本地线程的优先级
//
// JVM 规定本地线程的优先级为 1 - 10 之间的整数,优先级越高,本地线程被 CPU 调度的可能性越大
//
// 这里的优先级仅是建议性提示,是否生效取决于具体的调度策略
public final void setPriority(int newPriority) {

ThreadGroup g;
checkAccess();
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}

}

5.1.1.4. int getPriority()
1
2
3
4
5
6
// 用于非阻塞获取本地线程的优先级
public final int getPriority() {

return priority;

}

5.1.1.5. void join()
1
2
3
4
5
6
7
8
// 用于让本地线程进入阻塞状态,Thread 实例进入 WAITING 状态,并被投递到 Monitor 中的 WaitSet 队列,等待被唤醒(Obect#notify)、被中断
//
// 本地线程进入阻塞状态,Thread 实例进入 WAITING 状态后,能响应中断。线程被唤醒,重新获得 CPU 时间片后,会抛出 InterruptedException 受检异常,并清除 Thread 实例的中断状态(异常退出或正常退出(发生异常),要看我们是否对该异常进行捕获并处理)
public final void join() throws InterruptedException {

join(0);

}

5.1.1.6. void join(final long millis)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 用于让本地线程进入阻塞状态,Thread 实例进入 TIMED_WAITING 状态,并被投递到 Monitor 中的 WaitSet 队列,等待被唤醒(Obect#notify)、被中断、阻塞超时
//
// 本地线程进入阻塞状态,Thread 实例进入 TIMED_WAITING 状态后,能响应中断。线程被唤醒,重新获得 CPU 时间片后,会抛出 InterruptedException 受检异常,并清除 Thread 实例的中断状态(异常退出或正常退出(发生异常),要看我们是否对该异常进行捕获并处理)
public final synchronized void join(final long millis)

throws InterruptedException {
if (millis > 0) {
if (isAlive()) {
final long startTime = System.nanoTime();
long delay = millis;
do {
wait(delay);
} while (isAlive() && (delay = millis -
TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime)) > 0);
}
} else if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
throw new IllegalArgumentException("timeout value is negative");
}

}

[!NOTE] 注意事项

  1. 推荐使用 TimeUnit#timedJoin 替代该方法,因为其可读性更好
1
TimeUnit.MINUTES.timedJoin(worker, 1);

void join(long millis, int nanos)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 用于让本地线程进入阻塞状态,Thread 实例进入 TIMED_WAITING 状态,并被投递到 Monitor 中的 WaitSet 队列,等待被唤醒(Obect#notify)、被中断、阻塞超时
//
// 本地线程进入阻塞状态,Thread 实例进入 TIMED_WAITING 状态后,能响应中断。线程被唤醒,重新获得 CPU 时间片后,会抛出 InterruptedException 受检异常,并清除 Thread 实例的中断状态(异常退出或正常退出(发生异常),要看我们是否对该异常进行捕获并处理)
public final synchronized void join(long millis, int nanos) throws InterruptedException {

if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}

if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}

if (nanos > 0 && millis < Long.MAX_VALUE) {
millis++;
}

join(millis);

}

5.1.1.7. void setDaemon(boolean on)
1
2
3
4
5
6
7
8
9
10
// 用于非阻塞设置 Thread 实例为守护线程
public final void setDaemon(boolean on) {

checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;

}

5.1.1.8. boolean isInterrupted()
1
2
3
4
5
6
7
8
9
10
// 用于非阻塞查看 Thread 实例的中断状态
//
// 如果为 true,说明 Thread 实例被中断过
//
// 如果为 false,说明 Thread 实例没有被中断过
public boolean isInterrupted() {

return interrupted;

}

[!NOTE] 注意事项

  1. Thread.interruptedThread#isInterrupted 的区别在于:Thread.interrupted 会清除 Thread 实例的中断状态,而 Thread#isInterrupted 不会

5.1.1.9. boolean isAlive()
1
2
3
4
5
6
// 用于非阻塞查看本地线程是否存活
public final boolean isAlive() {

return eetop != 0;

}

5.1.2. 具体方法(实现)

5.1.2.1. Runnable 中接口方法的实现
5.1.2.1.1. void run()
1
2
3
4
5
6
7
public void run() {

if (target != null) {
target.run();
}

}

6. 静态方法

6.1. 静态具体方法

6.1.1. 具体方法(普通)

6.1.1.1. void sleep(long millis)
1
2
3
4
// 用于让本地线程进入阻塞状态,Thread 实例进入阻塞(TIMED_WAITING)状态,等待被中断、阻塞超时
//
// 本地线程进入阻塞状态,Thread 实例进入阻塞(TIMED_WAITING)状态后,能响应中断。线程被唤醒,重新获得 CPU 时间片后,会抛出 InterruptedException 受检异常,并清除 Thread 实例的中断状态(异常退出或正常退出(发生异常),要看我们是否对该异常进行捕获并处理)
public static native void sleep(long millis) throws InterruptedException;

[!NOTE] 注意事项

  1. 推荐使用 TimeUnit#sleep 替代该方法,因为其可读性更好
1
TimeUnit.HOURS.sleep(5);

6.1.1.2. void yield()
1
2
3
4
5
6
// 用于非阻塞提示线程调度器让出当前本地线程的 CPU 时间片
//
// 让出 CPU 时间片后,Thread 实例的状态会从 运行状态 ➔ 可运行状态
//
// 所谓的 “提示” 是指:仅是建议性提示,是否生效取决于具体的调度策略
public static native void yield();

[!NOTE] 注意事项

  1. 本地线程让出 CPU 时间片后,由于是可运行状态,可能会立即被其他 CPU 核重新调度。因此,在多核处理器或系统负载较低的情况下,该方法的效果可能并不明显。但是在单核环境或系统负载较高时,其调度行为会比较明显

6.1.1.3. Thread currentThread()
1
2
3
// 用于非阻塞获取执行当前 Java 代码的本地线程对应的 Thread 实例
@IntrinsicCandidate
public static native Thread currentThread();

6.1.1.4. boolean interrupted()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 用于非阻塞查看 Thread 实例的中断状态
//
// 如果为 true,说明 Thread 实例被中断过
//
// 如果为 false,说明 Thread 实例没有被中断过
public static boolean interrupted() {

Thread t = currentThread();
boolean interrupted = t.interrupted;
if (interrupted) {
// 清除 Thread 实例中的中断状态
t.interrupted = false;
clearInterruptEvent();
}
return interrupted;

}

[!NOTE] 注意事项

  1. Thread.interruptedThread#isInterrupted 的区别在于:Thread.interrupted 会清除 Thread 实例的中断状态,而 Thread#isInterrupted 不会


源码:java.lang.Thread 源码解析
https://wangjia5289.github.io/2025/11/12/源码:java.lang.Thread源码解析/
Author
咸阳猴🐒
Posted on
November 12, 2025
Licensed under