Thread类与线程生命周期
Thread 类是 Java 中用于实现多线程的核心类,位于 java.lang 包中,代表了一个线程的实例。在 Java 中,Thread 类提供了丰富的 API 用于创建和控制线程。
# 1. Thread 类的基本概念
- 线程:线程是程序执行的最小单元,每个线程都有自己的运行栈,用于执行独立的任务。在 Java 中,
Thread类用于创建和管理线程。 - 多线程的优势:通过多线程可以更好地利用多核 CPU 的性能,提高程序的并发性和响应速度。
# 2. Thread 类的主要构造方法
Thread 类提供了多种构造方法,用于灵活地创建线程:
无参构造方法:
public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); }- 创建一个默认的线程,线程名以 "Thread-" 开头,并自动分配一个唯一的编号。
使用
Runnable对象的构造方法:public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); }- 创建一个新线程,并将一个实现了
Runnable接口的对象作为线程的任务。
- 创建一个新线程,并将一个实现了
指定线程名称的构造方法:
public Thread(String name) { init(null, null, name, 0); }- 创建一个具有指定名称的线程。
使用
Runnable和线程名称的构造方法:public Thread(Runnable target, String name) { init(null, target, name, 0); }- 创建一个新线程,指定任务和线程名称。
# 3. Thread 类的核心方法
start():启动线程,使线程进入可运行状态。public synchronized void start() { if (threadStatus != 0) throw new IllegalThreadStateException(); group.add(this); start0(); }- 关键代码:
start0()是一个 native 方法,用于启动线程。 - 注意:只能调用一次
start()方法,多次调用会抛出IllegalThreadStateException。
- 关键代码:
run():线程执行的任务。默认情况下,run()方法会调用线程所持有的Runnable对象的run()方法。@Override public void run() { if (target != null) { target.run(); } }- 如果线程是通过
Runnable创建的,则调用target.run()。 - 可以通过继承
Thread类并重写run()方法来定义线程的执行内容。
- 如果线程是通过
Thread类中的start()和run()方法有明显的区别:
start()方法:
- 作用:用于启动线程。
- 过程:调用
start()方法后,Java 虚拟机会创建一个新的执行线程,并调用线程的run()方法。start()方法使线程进入可运行状态 (RUNNABLE),等待 JVM 调度执行。- 注意:只能调用一次
start()方法,多次调用会抛出IllegalThreadStateException。run()方法:
- 作用:定义线程的执行内容。
- 过程:
run()方法是线程的执行体,直接调用run()方法不会创建新线程,而是由当前线程顺序执行run()的代码。- 区别:如果直接调用
run(),它只是一个普通的方法调用,程序不会创建新的线程,执行不会并发,只是在当前线程中顺序运行。简单来说,
start()方法用于真正启动一个新线程,run()方法只是线程的任务逻辑。如果想要多线程并发运行,必须调用start()方法,而不是直接调用run()。
sleep(long millis):使当前线程休眠指定的毫秒数。public static native void sleep(long millis) throws InterruptedException;sleep()是一个静态方法,使调用它的线程进入休眠状态,从而释放 CPU 资源。- 注意:
sleep()不会释放锁资源。
join():等待当前线程执行完毕。public final void join() throws InterruptedException { join(0); }- 调用该方法的线程会等待目标线程完成后再继续执行。
- 可以指定超时时间,以避免无限期等待。
interrupt():中断线程。public void interrupt() { if (this != Thread.currentThread()) checkAccess(); synchronized (blockerLock) { Interruptible b = blocker; if (b != null) { interrupt0(); return; } } interrupt0(); }- 中断线程的执行状态。如果线程在
sleep()、wait()等阻塞状态下被中断,会抛出InterruptedException。 - 注意:中断并不会立刻停止线程,只是设置一个中断标志位,需要线程自己响应中断。
- 中断线程的执行状态。如果线程在
# 4. 线程状态
- NEW:新建状态,线程已经创建但尚未启动。当使用
new Thread()创建线程对象时,线程处于NEW状态。 - RUNNABLE:可运行状态,线程正在运行或等待分配 CPU 资源。调用
start()方法后,线程进入RUNNABLE状态,表示线程已准备好运行,由 JVM 的线程调度器决定何时执行。 - BLOCKED:阻塞状态,线程等待获取锁。当线程尝试获取已被其他线程持有的锁时,会进入
BLOCKED状态,直到获取到锁为止。 - WAITING:等待状态,线程等待另一个线程的通知。调用
Object.wait()、Thread.join()或LockSupport.park()方法时,线程会进入WAITING状态,等待其他线程的进一步操作。 - TIMED_WAITING:超时等待状态,线程等待指定时间。调用带有超时参数的方法(如
Thread.sleep(long millis)、Object.wait(long timeout)、Thread.join(long millis)等)时,线程会进入TIMED_WAITING状态,直到超时时间到期。 - TERMINATED:终止状态,线程执行完成或因异常退出。当线程的
run()方法执行完毕,或者抛出未捕获的异常而结束时,线程会进入TERMINATED状态。
# 5. Thread 类源码分析
线程的启动:
start()方法中调用了start0(),这是一个 native 方法,负责将线程从新建状态转为可运行状态。private native void start0();- 该方法是由 JVM 实现的,用于启动线程并请求操作系统分配资源。
线程中断:
interrupt()方法用于设置线程的中断状态。public void interrupt() { interrupt0(); } private native void interrupt0();interrupt0()也是一个 native 方法,用于通知底层系统中断线程。
线程休眠:
sleep()方法通过调用 native 方法来实现线程的休眠。public static native void sleep(long millis) throws InterruptedException;- 该方法会使线程进入阻塞状态,直到指定时间结束或被中断。
# 6. 使用 Thread 类实现多线程
继承 Thread 类:
class MyThread extends Thread { @Override public void run() { System.out.println("Thread is running"); } } MyThread thread = new MyThread(); thread.start();- 重写
run()方法来定义线程的任务,并调用start()方法启动线程。
- 重写
实现 Runnable 接口:
class MyRunnable implements Runnable { @Override public void run() { System.out.println("Runnable is running"); } } Thread thread = new Thread(new MyRunnable()); thread.start();- 推荐使用
Runnable接口,因为 Java 不支持多重继承,实现接口可以保持灵活性。
- 推荐使用
# 7. 总结
Thread 类是 Java 中用于实现多线程的基础类。通过继承 Thread 类或实现 Runnable 接口,可以创建并运行多线程。Thread 类提供了丰富的控制方法,如 start()、sleep()、interrupt() 等,以方便线程的管理和控制。对 Thread 类的源码分析有助于我们更好地理解线程的运行机制,从而编写出高效的并发代码。