Skip to content

线程基础

线程(Thread)是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。

1. 基本概念

1.1 进程与线程

概念说明
进程程序的一次执行过程,是系统运行程序的基本单位
线程比进程更小的执行单位,一个进程可以包含多个线程

主要区别

特性进程线程
资源分配独立的内存空间共享进程的内存空间
通信方式IPC(管道、消息队列等)直接读写共享变量
切换开销大(需要切换内存空间)小(同一进程内切换)
独立性相互独立共享进程资源

2. 创建线程的方式

方式一:继承 Thread 类

java
public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程运行中: " + Thread.currentThread().getName());
    }
    
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start(); // 启动线程
    }
}

特点

  • 简单直接
  • Java 单继承限制,无法继承其他类
  • 线程与任务耦合

方式二:实现 Runnable 接口(推荐)

java
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("线程运行中: " + Thread.currentThread().getName());
    }
    
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
        
        // 使用 Lambda 表达式(Java 8+)
        Thread thread2 = new Thread(() -> {
            System.out.println("Lambda 线程运行中");
        });
        thread2.start();
    }
}

特点

  • 任务与线程分离,更灵活
  • 可以继承其他类
  • 同一个 Runnable 可被多个线程共享
  • 推荐使用

方式三:实现 Callable 接口(可返回值)

java
import java.util.concurrent.*;

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        Thread.sleep(1000);
        return "任务执行完成";
    }
    
    public static void main(String[] args) throws Exception {
        FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
        Thread thread = new Thread(futureTask);
        thread.start();
        
        // 获取返回值(会阻塞直到完成)
        String result = futureTask.get();
        System.out.println(result);
    }
}

特点

  • 可以返回执行结果
  • 可以抛出异常
  • 需要配合 FutureTask 使用

三种方式对比

方式返回值异常处理继承限制推荐度
继承 Thread⭐⭐
实现 Runnable⭐⭐⭐⭐
实现 Callable⭐⭐⭐⭐⭐

3. 线程生命周期

3.1 六种状态

         start()           
NEW ──────────────► RUNNABLE ◄───────────────┐
                        │                     │
                        │                     │
              ┌─────────┼─────────┐           │
              │         │         │           │
              ▼         ▼         ▼           │
         BLOCKED    WAITING   TIMED_WAITING ──┘
              │         │         │
              └─────────┼─────────┘


                   TERMINATED
状态说明触发条件
NEW新建状态线程被创建但尚未调用 start()
RUNNABLE可运行状态调用 start() 后,包括就绪和运行中
BLOCKED阻塞状态等待获取 synchronized 锁
WAITING等待状态调用 wait()join()LockSupport.park()
TIMED_WAITING超时等待调用 sleep(n)wait(n)join(n)
TERMINATED终止状态线程执行完毕或异常退出

3.2 状态转换方法

java
// NEW → RUNNABLE
thread.start();

// RUNNABLE → TIMED_WAITING
Thread.sleep(1000);

// RUNNABLE → WAITING
object.wait();
thread.join();

// WAITING/TIMED_WAITING → RUNNABLE
object.notify();
object.notifyAll();

// RUNNABLE → BLOCKED
synchronized (lock) { ... }  // 等待获取锁

// RUNNABLE → TERMINATED
// run() 方法执行完毕

4. 常用方法

4.1 Thread 类方法

方法说明
start()启动线程
run()线程执行体(不要直接调用)
sleep(long ms)让线程休眠指定毫秒
join()等待该线程结束
interrupt()中断线程
isInterrupted()判断线程是否被中断
setName(String)设置线程名称
setPriority(int)设置线程优先级(1-10)
setDaemon(boolean)设置为守护线程

4.2 示例代码

java
public class ThreadMethodDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("线程被中断,退出");
                    return;
                }
                System.out.println("执行中: " + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt(); // 重新设置中断标志
                    return;
                }
            }
        });
        
        thread.setName("worker-thread");
        thread.start();
        
        Thread.sleep(2500);
        thread.interrupt(); // 中断线程
        
        thread.join(); // 等待线程结束
        System.out.println("主线程结束");
    }
}

5. 守护线程

守护线程(Daemon Thread)是为其他线程服务的后台线程,当所有非守护线程结束时,JVM 会退出,守护线程也随之终止。

java
Thread daemon = new Thread(() -> {
    while (true) {
        System.out.println("守护线程运行中...");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            break;
        }
    }
});

daemon.setDaemon(true);  // 必须在 start() 之前设置
daemon.start();

典型应用

  • 垃圾回收线程(GC)
  • 心跳检测线程
  • 日志记录线程

⚠️ 注意:守护线程中不要执行 IO 操作或持有资源,因为它可能随时被终止。