JDK 8 Thread
详解
Java 8 中的 Thread
类是实现多线程编程的核心组件,它封装了操作系统的线程机制,提供了创建、控制和管理线程的能力。以下是其核心原理和源码分析。
一、核心概念
1. 线程状态
- NEW:线程创建后尚未启动。
- RUNNABLE:正在 Java 虚拟机中执行,可能正在运行或等待 CPU 资源。
- BLOCKED:阻塞状态,等待获取监视器锁。
- WAITING:无限期等待,需其他线程显式唤醒(如
wait()
、join()
)。 - TIMED_WAITING:限时等待(如
sleep(long)
、wait(long)
)。 - TERMINATED:线程执行完毕,已终止。
Java线程状态流转流程图
2. 线程优先级
- 范围:1(最低)~ 10(最高),默认 5。
- 通过
setPriority(int)
方法设置,但不保证执行顺序。
3. 守护线程
- 通过
setDaemon(true)
设置,JVM 会在所有非守护线程结束后退出。
二、源码解析
1. 类定义与成员变量
public class Thread implements Runnable {
// 线程的底层句柄,由 JVM 实现
private long nativePeer;
// 线程名称
private String name;
// 线程优先级
private int priority;
// 是否为守护线程
private boolean daemon = false;
// 线程要执行的任务
private Runnable target;
// 线程组
private ThreadGroup group;
// 线程上下文类加载器
private ClassLoader contextClassLoader;
// 线程 ID
private long tid;
// 下一个线程 ID
private static long threadSeqNumber;
// 线程状态(0 表示 NEW)
private volatile int threadStatus = 0;
// 线程局部变量的映射表
ThreadLocal.ThreadLocalMap threadLocals = null;
// 继承的线程局部变量的映射表
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
// 线程栈大小(0 表示使用默认值)
private long stackSize;
// 线程终止时的返回值
private volatile Object result;
// 线程的 UncaughtExceptionHandler
private UncaughtExceptionHandler uncaughtExceptionHandler;
// 线程组默认的 UncaughtExceptionHandler
private static UncaughtExceptionHandler defaultUncaughtExceptionHandler;
// 内部枚举:线程状态
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
}
2. 构造函数
// 默认构造函数
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
// 带 Runnable 任务的构造函数
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
// 带线程组和 Runnable 任务的构造函数
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
// 初始化线程的核心方法
private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
init(g, target, name, stackSize, null, true);
}
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();
}
}
// 检查权限
g.checkAccess();
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted();
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 : AccessController.getContext();
// 设置 Runnable 任务
this.target = target;
// 设置优先级
setPriority(priority);
// 继承父线程的线程局部变量
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
// 设置线程栈大小
this.stackSize = stackSize;
// 生成线程 ID
tid = nextThreadID();
}
3. 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) {
// 什么也不做,只有在 group 为 null 时才会发生
}
}
}
// 本地方法:由 JVM 实现线程启动逻辑
private native void start0();
4. run() 方法
@Override
public void run() {
if (target != null) {
// 执行 Runnable 任务
target.run();
}
}
5. sleep(long millis) 方法
public static native void sleep(long millis) 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);
}
6. join() 方法
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;
}
}
}
public final synchronized void join(long millis, int nanos) throws InterruptedException {
// 实现类似 sleep(long, int) 的逻辑,最终调用 wait(long)
}
public final void join() throws InterruptedException {
join(0);
}
7. yield() 方法
public static native void yield();
8. interrupt() 方法
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // 首先设置中断标志
b.interrupt(this);
return;
}
}
// 设置中断标志
interrupt0();
}
// 本地方法:设置线程的中断标志
private native void interrupt0();
9. isInterrupted() 方法
public boolean isInterrupted() {
return isInterrupted(false);
}
// 本地方法:检查线程的中断状态
private native boolean isInterrupted(boolean ClearInterrupted);
// 静态方法:检查当前线程的中断状态,并清除中断标志
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
三、关键特性分析
1. 线程创建与启动
- 继承 Thread 类:重写
run()
方法。class MyThread extends Thread { @Override public void run() { System.out.println("Running in MyThread"); } } // 使用 MyThread t = new MyThread(); t.start();
- 实现 Runnable 接口:更灵活,支持多继承。
class MyRunnable implements Runnable { @Override public void run() { System.out.println("Running in MyRunnable"); } } // 使用 Thread t = new Thread(new MyRunnable()); t.start();
2. 线程同步与协作
- wait()/notify()/notifyAll():基于对象监视器的线程间通信。
public synchronized void producer() { while (buffer.isFull()) { wait(); // 等待消费者 } // 生产数据 notifyAll(); // 通知消费者 }
- join():等待线程执行完毕。
Thread t = new Thread(...); t.start(); t.join(); // 等待 t 线程执行完毕
- yield():提示调度器当前线程愿意让出 CPU 资源。
3. 中断机制
- interrupt():设置线程的中断标志。
- isInterrupted():检查中断标志,不清除。
- interrupted():检查中断标志并清除。
public void run() { while (!Thread.currentThread().isInterrupted()) { // 执行任务 } }
四、使用场景
-
异步任务:将耗时操作放在独立线程中执行。
new Thread(() -> { // 执行耗时操作 }).start();
-
并行计算:多核 CPU 下提高计算效率。
Thread t1 = new Thread(() -> computePart1()); Thread t2 = new Thread(() -> computePart2()); t1.start(); t2.start(); t1.join(); t2.join();
-
定时任务:结合
sleep()
实现简单定时任务。new Thread(() -> { while (true) { doTask(); try { Thread.sleep(1000); // 每秒执行一次 } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } }).start();
五、注意事项
-
线程安全:多线程访问共享资源时需使用同步机制(如
synchronized
、Lock
)。 -
避免死锁:合理设计锁的获取顺序,使用
Lock
的tryLock()
方法。 -
资源释放:线程执行完毕后,确保释放资源(如文件句柄、网络连接)。
-
线程池:避免手动创建大量线程,使用线程池管理线程(如
ExecutorService
)。
六、总结
JDK 8 的 Thread
类是 Java 多线程编程的基础,通过封装操作系统线程机制,提供了创建、控制和管理线程的能力。理解其核心方法(如 start()
、run()
、sleep()
、join()
、interrupt()
)和状态转换机制,有助于编写高效、安全的多线程程序。在实际开发中,应优先使用线程池(如 ExecutorService
)而非手动创建线程,以提高资源利用率和程序稳定性。