JDK 8 Thread 详解及详细源码展示

JDK 8 Thread 详解

Java 8 中的 Thread 类是实现多线程编程的核心组件,它封装了操作系统的线程机制,提供了创建、控制和管理线程的能力。以下是其核心原理和源码分析。

一、核心概念

1. 线程状态
  • NEW:线程创建后尚未启动。
  • RUNNABLE:正在 Java 虚拟机中执行,可能正在运行或等待 CPU 资源。
  • BLOCKED:阻塞状态,等待获取监视器锁。
  • WAITING:无限期等待,需其他线程显式唤醒(如 wait()join())。
  • TIMED_WAITING:限时等待(如 sleep(long)wait(long))。
  • TERMINATED:线程执行完毕,已终止。

Java线程状态流转流程图

start()
获取锁
锁释放
wait()/join()/park()
notify()/notifyAll()/unpark()
sleep()/wait(timeout)/join(timeout)
超时/被唤醒
run()结束/异常
NEW
RUNNABLE
BLOCKED
WAITING
TIMED_WAITING
TERMINATED
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()) {
            // 执行任务
        }
    }
    

四、使用场景

  1. 异步任务:将耗时操作放在独立线程中执行。

    new Thread(() -> {
        // 执行耗时操作
    }).start();
    
  2. 并行计算:多核 CPU 下提高计算效率。

    Thread t1 = new Thread(() -> computePart1());
    Thread t2 = new Thread(() -> computePart2());
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    
  3. 定时任务:结合 sleep() 实现简单定时任务。

    new Thread(() -> {
        while (true) {
            doTask();
            try {
                Thread.sleep(1000); // 每秒执行一次
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
        }
    }).start();
    

五、注意事项

  1. 线程安全:多线程访问共享资源时需使用同步机制(如 synchronizedLock)。

  2. 避免死锁:合理设计锁的获取顺序,使用 LocktryLock() 方法。

  3. 资源释放:线程执行完毕后,确保释放资源(如文件句柄、网络连接)。

  4. 线程池:避免手动创建大量线程,使用线程池管理线程(如 ExecutorService)。

六、总结

JDK 8 的 Thread 类是 Java 多线程编程的基础,通过封装操作系统线程机制,提供了创建、控制和管理线程的能力。理解其核心方法(如 start()run()sleep()join()interrupt())和状态转换机制,有助于编写高效、安全的多线程程序。在实际开发中,应优先使用线程池(如 ExecutorService)而非手动创建线程,以提高资源利用率和程序稳定性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值