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
类的源码分析有助于我们更好地理解线程的运行机制,从而编写出高效的并发代码。