一、线程生命周期相关方法

作用:控制线程从创建到终止的全流程,是线程操作的基础。

方法 作用 调用者 注意事项
start() 启动新线程(JVM 创建线程并调用run() 线程对象 ① 仅能调用 1 次,重复调用抛IllegalThreadStateException;② 直接调用run()是普通方法,不启动新线程。
run() 线程执行体(定义任务逻辑) 线程对象 需通过重写Thread或传入Runnable定义;无需手动调用(由start()触发)。
isAlive() 判断线程是否存活(启动后未终止) 线程对象 start()或已终止的线程返回false
join()join(long millis) 当前线程等待目标线程执行完毕(或超时) 目标线程对象 ① 如t.join():主线程等待t执行完再继续;② 本质是通过wait()实现,会释放锁。

示例:start() vs run() + join()

public class ThreadLifecycle {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            // 子线程任务:循环输出
            for (int i = 0; i < 3; i++) {
                System.out.println("子线程执行:" + i);
                try { Thread.sleep(500); } // 模拟耗时
                catch (InterruptedException e) {}
            }
        }, "子线程");

        // 1. 启动新线程(JVM调用run())
        t.start(); 
        // 若直接调用t.run(),会在主线程中执行,不创建新线程

        // 2. 主线程等待子线程执行完毕
        t.join(); // 阻塞主线程,直到t执行结束
        System.out.println("主线程:子线程已结束,我继续执行");
    }
}
/* 输出:
子线程执行:0
子线程执行:1
子线程执行:2
主线程:子线程已结束,我继续执行
*/

二、线程控制与中断方法

作用:控制线程执行节奏(暂停、让出 CPU)或通过中断机制协作终止线程。

方法 作用 调用者 注意事项
sleep(long millis) 当前线程暂停指定毫秒(让出 CPU) 静态方法(Thread ① 不释放同步锁(synchronized);② 时间到后回到就绪状态;③ 可被interrupt()中断,抛InterruptedException
yield() 当前线程让出 CPU,重新参与调度 静态方法(Thread ① 仅为 JVM 调度建议,不一定生效;② 不释放锁,适合同优先级线程礼让。
interrupt() 设置线程中断标志(非强制终止) 线程对象 ① 若线程阻塞(sleep/wait等),抛InterruptedException并清除标志;② 需线程内部判断标志并处理终止。
isInterrupted() 判断线程是否被中断(不清除标志) 线程对象 线程内部用:while(!isInterrupted())控制退出逻辑。
interrupted() 判断当前线程是否被中断(清除标志) 静态方法(Thread 用于捕获异常后重置中断状态(如Thread.interrupted())。

示例:sleep()interrupt()协作

public class ThreadControl {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            try {
                System.out.println("子线程:开始休眠10秒");
                Thread.sleep(10000); // 休眠(阻塞状态)
            } catch (InterruptedException e) {
                // 被interrupt()中断时触发
                System.out.println("子线程:被中断,休眠结束");
                // 异常会清除中断标志,此处输出false
                System.out.println("中断标志:" + Thread.currentThread().isInterrupted()); 
            }
        });
        t.start();

        // 主线程3秒后中断子线程
        try { Thread.sleep(3000); } catch (InterruptedException e) {}
        t.interrupt(); // 设置中断标志,唤醒阻塞的子线程
    }
}
/* 输出:
子线程:开始休眠10秒
子线程:被中断,休眠结束
中断标志:false
*/

三、线程通信方法(Object类)

作用:多线程间协作(如生产者 - 消费者模型),必须在同步块 / 方法中使用(依赖锁)。

方法 作用 调用者 注意事项
wait()wait(long timeout) 释放锁并进入等待状态(直到被唤醒 / 超时) 同步锁对象 ① 必须在synchronized(锁对象)中调用;② 唤醒后需重新竞争锁;③ 用while循环判断条件(防虚假唤醒)。
notify() 唤醒一个等待当前锁的线程(随机) 同步锁对象 ① 需在同步块中调用;② 唤醒后线程需等当前线程释放锁才能执行。
notifyAll() 唤醒所有等待当前锁的线程 同步锁对象 适用于资源充足时,唤醒全部等待者(如库存补充后唤醒所有消费者)。

示例:生产者 - 消费者模型(wait()+notify()

public class ThreadCommunication {
    private static int count = 0; // 共享资源(库存)
    private static final Object lock = new Object(); // 同步锁

    // 生产者:增加库存
    static class Producer extends Thread {
        @Override
        public void run() {
            synchronized (lock) {
                count++; // 生产
                System.out.println("生产者:库存=" + count);
                lock.notify(); // 唤醒等待的消费者
            }
        }
    }

    // 消费者:消耗库存
    static class Consumer extends Thread {
        @Override
        public void run() {
            synchronized (lock) {
                // 循环判断(防虚假唤醒:即使被意外唤醒,仍需检查条件)
                while (count == 0) { 
                    try {
                        System.out.println("消费者:等待库存...");
                        lock.wait(); // 释放锁,进入等待
                    } catch (InterruptedException e) {}
                }
                count--; // 消费
                System.out.println("消费者:消费后库存=" + count);
            }
        }
    }

    public static void main(String[] args) {
        new Consumer().start(); // 消费者先启动(等待库存)
        new Producer().start(); // 生产者生产后唤醒消费者
    }
}
/* 输出:
消费者:等待库存...
生产者:库存=1
消费者:消费后库存=0
*/

四、线程属性方法

作用:设置 / 获取线程的标识、优先级、守护状态等属性。

方法 作用 调用者 注意事项
setName(String)/getName() 设置 / 获取线程名称(调试用) 线程对象 名称仅用于标识(如日志输出),无功能影响。
setPriority(int)/getPriority() 设置 / 获取优先级(1-10,默认 5) 线程对象 ① 优先级高的线程更可能被调度(非绝对);② 范围:MIN_PRIORITY(1)~MAX_PRIORITY(10)
setDaemon(boolean)/isDaemon() 设置 / 判断守护线程(后台线程) 线程对象 ① 必须在start()前设置;② 依赖用户线程:所有用户线程结束,守护线程自动终止(如 GC 线程)。

示例:守护线程(后台线程)

public class DaemonThread {
    public static void main(String[] args) {
        Thread daemon = new Thread(() -> {
            // 守护线程任务:无限循环(仅守护线程可安全使用)
            while (true) { 
                System.out.println("守护线程运行中...");
                try { Thread.sleep(1000); } catch (InterruptedException e) {}
            }
        });
        daemon.setDaemon(true); // 标记为守护线程(必须在start前)
        daemon.start();

        // 主线程(用户线程)运行3秒后结束
        try { Thread.sleep(3000); } catch (InterruptedException e) {}
        System.out.println("主线程结束,守护线程自动终止");
    }
}
/* 输出(约3秒后停止):
守护线程运行中...
守护线程运行中...
守护线程运行中...
主线程结束,守护线程自动终止
*/

五、方法的对比

对比项 关键差异
start() vs run() start()启动新线程;run()是普通方法,在当前线程执行。
sleep() vs wait() sleep不释放锁(Thread方法);wait释放锁(Object方法,需同步块)。
notify() vs notifyAll() notify唤醒一个线程;notifyAll唤醒所有线程(均需同步块)。
interrupt() 作用 不直接终止线程,仅设置中断标志;需线程通过isInterrupted()主动响应。

sleep () vs wait () 区别(聚焦「锁与系统资源」)

1. sleep () 的关键特性(重点)
  • 让出系统资源(CPU):无论是否加锁,调用 sleep() 都会让当前线程暂停,释放 CPU 时间片(让其他线程有机会获得 CPU 执行)—— 这是 “让出系统资源” 的核心含义。
  • 是否释放锁?分场景
    • 非线程安全(不加锁):没有锁可释放,其他线程能正常执行(因为 CPU 被让出了)。
    • 线程安全(加锁,同步块 / 方法内)不释放锁(抱着锁睡)。此时虽然 CPU 被让出,但其他线程若需要同一把锁,会被阻塞(无法执行同步代码)。
2. wait () 的关键特性
  • 必须在加锁场景(同步块 / 方法)中调用:否则直接抛异常。
  • 既让出系统资源(CPU),又释放锁:调用 wait() 后,当前线程会释放持有的锁,其他线程可以获取锁执行同步代码;同时线程进入等待状态,需被 notify()/notifyAll() 唤醒。
总结
  • sleep():无论是否加锁,都会让出 CPU(系统资源);但加锁时不释放锁(抱着锁睡),其他线程拿不到锁就执行不了同步代码;不加锁时,其他线程能正常执行。

  • wait():必须在加锁场景用,既让出 CPU,又释放锁,其他线程能抢锁执行同步代码,需被 notify 唤醒。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐