JDK 8 Thread 源码详解(完整版带详细注释)
1. 基本结构和常量定义
public class Thread implements Runnable {
// 线程状态枚举
public enum State {
// 新建状态:线程被创建但尚未启动
NEW,
// 可运行状态:线程正在JVM中执行,可能正在等待CPU时间片
RUNNABLE,
// 阻塞状态:线程被阻塞等待监视器锁
BLOCKED,
// 等待状态:线程无限期等待其他线程执行特定操作
WAITING,
// 超时等待状态:线程等待其他线程执行特定操作,但有时间限制
TIMED_WAITING,
// 终止状态:线程已执行完毕
TERMINATED;
}
// 线程优先级常量
public final static int MIN_PRIORITY = 1; // 最低优先级
public final static int NORM_PRIORITY = 5; // 默认优先级
public final static int MAX_PRIORITY = 10; // 最高优先级
// 序列化版本号
private static final long serialVersionUID = 6421047171450067389L;
// 用于生成线程ID的原子计数器
private static volatile long threadSeqNumber;
// 线程初始化数量,用于JVM关闭时的判断
private static volatile int threadInitNumber;
// 线程组
private volatile ThreadGroup group;
// 线程的唯一标识符
private volatile long tid;
// 线程名称
private volatile String name;
// 线程优先级
private volatile int priority;
// 是否为守护线程
private volatile boolean daemon = false;
// JVM状态标志
private volatile boolean stillborn = false;
// 线程要执行的任务
private Runnable target;
// 该线程的ThreadLocal值的副本
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
// 线程栈大小(如果为0表示使用默认值)
private long stackSize;
// 本地线程ID,供JVM内部使用
private long nativeParkEventPointer;
// 线程状态
private volatile int threadStatus = 0;
// 线程中断状态
private volatile Interruptible blocker;
private final Object blockerLock = new Object();
// 线程可以拥有的最大优先级
private static int threadPriorityOverInheritableThreadLocals = 0;
// 线程中断标志
private volatile boolean interrupted = false;
// 线程是否已经被启动
private boolean started = false;
}
2. 构造函数
/**
* 无参构造函数
* 分配一个新的Thread对象
*/
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
/**
* 指定Runnable目标的构造函数
* @param target 线程要执行的任务
*/
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
/**
* 指定线程组和Runnable目标的构造函数
* @param group 线程组
* @param target 线程要执行的任务
*/
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
/**
* 指定线程名称的构造函数
* @param name 线程名称
*/
public Thread(String name) {
init(null, null, name, 0);
}
/**
* 指定线程组和线程名称的构造函数
* @param group 线程组
* @param name 线程名称
*/
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}
/**
* 指定Runnable目标和线程名称的构造函数
* @param target 线程要执行的任务
* @param name 线程名称
*/
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
/**
* 指定线程组、Runnable目标和线程名称的构造函数
* @param group 线程组
* @param target 线程要执行的任务
* @param name 线程名称
*/
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}
/**
* 指定线程组、Runnable目标、线程名称和栈大小的构造函数
* @param group 线程组
* @param target 线程要执行的任务
* @param name 线程名称
* @param stackSize 线程栈大小
*/
public Thread(ThreadGroup group, Runnable target, String name,
long stackSize) {
init(group, target, name, stackSize);
}
3. 初始化方法
/**
* 线程初始化方法
* @param g 线程组
* @param target 线程要执行的任务
* @param name 线程名称
* @param stackSize 线程栈大小
*/
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
init(g, target, name, stackSize, null, true);
}
/**
* 线程初始化方法(完整版本)
* @param g 线程组
* @param target 线程要执行的任务
* @param name 线程名称
* @param stackSize 线程栈大小
* @param acc 访问控制器上下文
* @param inheritThreadLocals 是否继承父线程的ThreadLocal值
*/
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name; // 设置线程名称
Thread parent = currentThread(); // 获取当前线程作为父线程
SecurityManager security = System.getSecurityManager();
if (g == null) {
// 如果没有指定线程组,使用父线程的线程组
if (security != null) {
g = security.getThreadGroup();
if (g == null) {
g = parent.getThreadGroup();
}
} else {
g = parent.getThreadGroup();
}
}
// 检查是否有权限访问线程组
g.checkAccess();
// 检查是否有权限创建线程
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted(); // 线程组中未启动线程数加1
this.group = g; // 设置线程组
this.daemon = parent.isDaemon(); // 继承父线程的守护线程属性
this.priority = parent.getPriority(); // 继承父线程的优先级
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : parent.inheritedAccessControlContext;
this.threadLocals = null;
this.inheritableThreadLocals = null;
this.target = target; // 设置线程要执行的任务
setPriority(priority); // 设置优先级
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
this.stackSize = stackSize; // 设置栈大小
tid = nextThreadID(); // 生成线程ID
}
4. 核心方法实现
4.1 start方法
/**
* 启动线程
* 使该线程开始执行;JVM调用该线程的run方法
* @throws IllegalThreadStateException 如果线程已经启动
*/
public synchronized void start() {
// 检查线程状态,确保线程只启动一次
if (threadStatus != 0)
throw new IllegalThreadStateException();
// 将线程添加到线程组中
group.add(this);
boolean started = false;
try {
// 调用native方法启动线程
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
// 忽略异常
}
}
}
// 本地方法,由JVM实现
private native void start0();
4.2 run方法
/**
* 线程执行的主要方法
* 如果线程是使用单独的Runnable对象构造的,则调用该Runnable对象的run方法;
* 否则此方法不执行任何操作并返回
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
4.3 exit方法
/**
* 线程退出时调用此方法
* 不是public方法,由JVM在线程结束时调用
*/
private void exit() {
if (group != null) {
group.threadTerminated(this);
group = null;
}
// 清理ThreadLocal
threadLocals = null;
inheritableThreadLocals = null;
target = null;
// 加速垃圾回收
uncaughtExceptionHandler = null;
}
5. 线程控制方法
5.1 sleep方法
/**
* 使当前正在执行的线程休眠指定的毫秒数
* @param millis 休眠的毫秒数
* @throws InterruptedException 如果线程被中断
*/
public static native void sleep(long millis) throws InterruptedException;
/**
* 使当前正在执行的线程休眠指定的毫秒数和纳秒数
* @param millis 休眠的毫秒数
* @param nanos 0-999999额外的纳秒数
* @throws InterruptedException 如果线程被中断
*/
public static void sleep(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 >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
sleep(millis);
}
5.2 yield方法
/**
* 暂停当前线程的执行,让出CPU时间片给其他同优先级的线程
* 注意:这只是建议,JVM可能忽略这个建议
*/
public static native void yield();
5.3 join方法
/**
* 等待该线程终止
* @throws InterruptedException 如果当前线程被中断
*/
public final void join() throws InterruptedException {
join(0);
}
/**
* 等待该线程终止,最多等待millis毫秒
* @param millis 等待的毫秒数
* @throws InterruptedException 如果当前线程被中断
*/
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
// 无限等待直到线程终止
while (isAlive()) {
wait(0);
}
} else {
// 等待指定时间
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
/**
* 等待该线程终止,最多等待millis毫秒和nanos纳秒
* @param millis 等待的毫秒数
* @param nanos 0-999999额外的纳秒数
* @throws InterruptedException 如果当前线程被中断
*/
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 >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
join(millis);
}
6. 线程状态管理
6.1 线程状态获取
/**
* 返回该线程的状态
* @return 线程的当前状态
*/
public State getState() {
// 获取线程状态的快照
return sun.misc.VM.toThreadState(threadStatus);
}
6.2 守护线程设置
/**
* 将该线程标记为守护线程或用户线程
* @param on true表示守护线程,false表示用户线程
* @throws IllegalThreadStateException 如果线程已经启动
*/
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}
/**
* 测试该线程是否为守护线程
* @return 如果该线程是守护线程返回true
*/
public final boolean isDaemon() {
return daemon;
}
6.3 线程优先级设置
/**
* 更改线程的优先级
* @param newPriority 新的优先级
* @throws IllegalArgumentException 如果优先级超出范围
* @throws SecurityException 如果当前线程无法修改该线程
*/
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);
}
}
/**
* 返回线程的优先级
* @return 线程的优先级
*/
public final int getPriority() {
return priority;
}
// 本地方法,由JVM实现
private native void setPriority0(int newPriority);
7. 线程中断机制
7.1 中断相关方法
/**
* 中断该线程
* 如果该线程被wait()、join()、sleep()等方法阻塞,
* 则会抛出InterruptedException并清除中断状态
* 否则只是设置中断标志位
*/
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // 只设置中断标志
b.interrupt(this);
return;
}
}
interrupt0();
}
/**
* 测试当前线程是否已被中断
* 调用此方法会清除中断状态
* @return 如果当前线程已被中断返回true
*/
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
/**
* 测试该线程是否已被中断
* 不会清除中断状态
* @return 如果该线程已被中断返回true
*/
public boolean isInterrupted() {
return isInterrupted(false);
}
/**
* 测试线程是否已被中断
* @param ClearInterrupted true表示清除中断状态,false表示不清除
* @return 如果线程已被中断返回true
*/
private native boolean isInterrupted(boolean ClearInterrupted);
// 本地方法,由JVM实现
private native void interrupt0();
7.2 中断检查方法
/**
* 如果当前线程已被中断,则抛出InterruptedException
* @throws InterruptedException 如果当前线程已被中断
*/
public static void sleep(long millis) throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
// 这里会检查中断状态,如果被中断则抛出异常
Thread.sleep(millis);
}
8. 线程基本信息
8.1 线程名称管理
/**
* 改变线程名称
* @param name 新的线程名称
* @throws SecurityException 如果当前线程无法修改该线程
*/
public final synchronized void setName(String name) {
checkAccess();
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
if (threadStatus != 0) {
setNativeName(name);
}
}
/**
* 返回该线程的名称
* @return 线程名称
*/
public final String getName() {
return name;
}
// 本地方法,由JVM实现
private native void setNativeName(String name);
8.2 线程组管理
/**
* 返回该线程所属的线程组
* @return 线程组
*/
public final ThreadGroup getThreadGroup() {
return group;
}
8.3 线程ID管理
/**
* 返回该线程的标识符
* @return 线程ID
*/
public long getId() {
return tid;
}
9. 线程活动状态
/**
* 测试该线程是否处于活动状态
* 活动状态意味着线程已启动且尚未终止
* @return 如果线程处于活动状态返回true
*/
public final native boolean isAlive();
10. 线程本地存储
10.1 ThreadLocal相关方法
/**
* 返回该线程的ThreadLocal值的副本
* @return ThreadLocalMap
*/
ThreadLocal.ThreadLocalMap getThreadLocals() {
return threadLocals;
}
/**
* 设置该线程的ThreadLocal值的副本
* @param threadLocals ThreadLocalMap
*/
void setThreadLocals(ThreadLocal.ThreadLocalMap threadLocals) {
this.threadLocals = threadLocals;
}
/**
* 返回该线程的可继承ThreadLocal值的副本
* @return ThreadLocalMap
*/
ThreadLocal.ThreadLocalMap getInheritableThreadLocals() {
return inheritableThreadLocals;
}
/**
* 设置该线程的可继承ThreadLocal值的副本
* @param inheritableThreadLocals ThreadLocalMap
*/
void setInheritableThreadLocals(ThreadLocal.ThreadLocalMap inheritableThreadLocals) {
this.inheritableThreadLocals = inheritableThreadLocals;
}
11. 线程上下文类加载器
/**
* 设置该线程的上下文类加载器
* @param cl 类加载器
* @throws SecurityException 如果当前线程无法设置上下文类加载器
*/
public void setContextClassLoader(ClassLoader cl) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
}
contextClassLoader = cl;
}
/**
* 返回该线程的上下文类加载器
* @return 类加载器
*/
public ClassLoader getContextClassLoader() {
if (contextClassLoader == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(contextClassLoader,
Reflection.getCallerClass());
}
return contextClassLoader;
}
12. 线程检查和安全
/**
* 确定当前运行的线程是否有权限修改该线程
* @throws SecurityException 如果当前线程无法修改该线程
*/
public final void checkAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkAccess(this);
}
}
13. 线程统计和工具方法
13.1 线程计数
/**
* 返回活动线程的当前数目
* @return 活动线程数
*/
public static int activeCount() {
return currentThread().getThreadGroup().activeCount();
}
/**
* 将当前线程的线程组及其子组中的每个活动线程复制到指定数组
* @param tarray 存放线程的数组
* @return 放入数组的线程数
*/
public static int enumerate(Thread tarray[]) {
return currentThread().getThreadGroup().enumerate(tarray);
}
13.2 当前线程获取
/**
* 返回对当前正在执行的线程对象的引用
* @return 当前线程
*/
public static native Thread currentThread();
13.3 线程转储
/**
* 打印线程的堆栈跟踪
* @param t 要打印堆栈跟踪的线程
*/
public static void dumpStack() {
new Exception("Stack trace").printStackTrace();
}
14. 线程异常处理
/**
* 线程未捕获异常处理器接口
*/
@FunctionalInterface
public interface UncaughtExceptionHandler {
/**
* 当线程因未捕获异常而突然终止时调用此方法
* @param t 发生异常的线程
* @param e 未捕获的异常
*/
void uncaughtException(Thread t, Throwable e);
}
/**
* 设置该线程的未捕获异常处理器
* @param eh 异常处理器
*/
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
checkAccess();
uncaughtExceptionHandler = eh;
}
/**
* 返回该线程的未捕获异常处理器
* @return 异常处理器
*/
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
return uncaughtExceptionHandler != null ?
uncaughtExceptionHandler : group;
}
/**
* 返回线程默认的未捕获异常处理器
* @return 默认异常处理器
*/
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
return defaultUncaughtExceptionHandler;
}
/**
* 设置线程默认的未捕获异常处理器
* @param eh 默认异常处理器
*/
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(
new RuntimePermission("setDefaultUncaughtExceptionHandler")
);
}
defaultUncaughtExceptionHandler = eh;
}
15. 总结
15.1 Thread类的特点
- 线程生命周期管理:提供了完整的线程创建、启动、执行、终止机制
- 线程状态控制:支持线程的休眠、等待、中断等操作
- 线程优先级:支持线程优先级设置,影响线程调度
- 守护线程支持:可以设置守护线程,JVM退出时不等待守护线程完成
- 线程安全机制:提供了同步和互斥机制
- 中断机制:完善的线程中断处理机制
- 异常处理:支持未捕获异常的处理
15.2 线程生命周期
// 线程生命周期示例
/*
NEW(新建) -> start() -> RUNNABLE(可运行)
RUNNABLE <-> BLOCKED/WAITING/TIMED_WAITING(阻塞/等待)
RUNNABLE -> TERMINATED(终止)
*/
15.3 重要设计模式
- 模板方法模式:run()方法是模板方法
- 代理模式:通过target执行实际任务
- 观察者模式:UncaughtExceptionHandler处理异常
15.4 使用建议
-
线程创建:
- 优先使用线程池而不是直接创建Thread
- 合理设置线程名称便于调试
-
线程安全:
- 正确使用同步机制
- 注意线程间的数据共享
-
资源管理:
- 及时清理ThreadLocal
- 合理设置线程优先级
-
异常处理:
- 设置合适的UncaughtExceptionHandler
- 处理InterruptedException
15.5 性能考虑
- 线程创建开销:线程创建和销毁都有开销,考虑使用线程池
- 上下文切换:过多线程会导致频繁的上下文切换
- 内存占用:每个线程都需要栈空间
- 同步开销:过度同步会影响性能
Thread类是Java并发编程的基础,理解其内部机制对于编写高质量的并发程序至关重要。