Java 线程重点 面试笔记(线程状态,安全停止线程..)
包括线程状态、Thread.yield()、Thread.join()、线程安全停止、标志位、中断等,都是线程这块秋招的重点。
1. 线程状态(Thread.State)
Java 中线程有 6 种状态:
状态 | 含义 | 进入条件 |
---|---|---|
NEW | 新建状态 | Thread t = new Thread(...); |
RUNNABLE | 可运行状态 | 调用 start() 后,等待 CPU 调度 |
BLOCKED | 阻塞状态 | 等待锁(synchronized) |
WAITING | 无时间限制等待 | Object.wait()、Thread.join()(无超时)、LockSupport.park() |
TIMED_WAITING | 有时间限制的等待 | sleep(millis)、join(millis)、wait(millis) |
TERMINATED | 终止状态 | 线程执行完 run() 方法 |
注意:
RUNNABLE 不一定在 CPU 上运行,只是处于可运行队列中。
BLOCKED、WAITING、TIMED_WAITING 是阻塞线程状态。
2. Thread.yield()
作用:提示线程调度器,当前线程愿意让出 CPU,但只是“礼貌性提示”,不保证立即切换。
效果:线程从 RUNNING → RUNNABLE,允许同优先级线程运行。
特点:
不阻塞线程
不释放锁
示例:
for (int i = 0; i < 10; i++) {System.out.println(i);Thread.yield(); // 提示调度器切换线程
}
3. Thread.join()
作用:让当前线程等待调用 join() 的线程执行完成。
效果:当前线程进入 WAITING 或 TIMED_WAITING,直到被等待的线程 TERMINATED。
可选超时:join(long millis),超时后线程继续执行。
示例:
Thread a = new Thread(() -> System.out.println("线程A执行"));
a.start();
a.join(); // 当前线程等待a执行完
System.out.println("主线程继续");
4. 安全停止线程
4.1 原则
Java 不推荐使用 stop()、suspend()、resume(),会破坏资源和锁,容易死锁。
推荐方式:使用标志位(flag)或 interrupt() 请求中断。
4.2 标志位(Flag)
概念:线程内部定义的布尔变量,用于表示线程是否继续运行。
特点:
线程自己检查标志位决定是否退出
使用 volatile 修饰保证线程可见性
这里使用volatile是因为,volatile可以使当前变量的变化能立即被别的线程看到。
示例:
class DownloadTask implements Runnable {private volatile boolean running = true;public void stop() {running = false;}@Overridepublic void run() {while (running) {System.out.println("下载中...");}System.out.println("线程停止");}
}
4.3 中断线程(Interrupt)
概念:interrupt() 不是直接停止线程,而是发出中断请求,线程自己决定是否退出。
阻塞线程:sleep()、wait()、join() 会抛 InterruptedException。
非阻塞循环:线程需检查 isInterrupted() 或结合标志位。
示例:
class DownloadTask implements Runnable {@Overridepublic void run() {while (!Thread.currentThread().isInterrupted()) {try {Thread.sleep(500); // 阻塞操作,可响应中断} catch (InterruptedException e) {Thread.currentThread().interrupt(); // 重新设置中断标志break; // 安全退出循环}System.out.println("下载中...");}System.out.println("线程安全停止");}
}Thread t = new Thread(new DownloadTask());
t.start();
Thread.sleep(2000);
t.interrupt(); // 请求停止线程
核心理解:
interrupt() 只是一种请求,不强制停止
循环型任务检查中断标志,阻塞任务捕获异常退出
标志位适合循环任务,interrupt 适合阻塞任务
5. 小结
线程状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED
yield():礼貌性让出 CPU
join():等待线程完成,可带超时
安全停止线程:
循环任务用 标志位
阻塞任务用 interrupt() + 异常处理
阻塞 vs 非阻塞:阻塞线程可响应 interrupt,非阻塞线程需自己检查标志