Java 线程基础:进程、线程、并发并行、创建方式与生命周期

Java 并发面试的第一层,通常不是上来就问 AQS 和锁升级,而是先看你能不能把几个基础概念说清楚。

进程是什么,线程是什么,并发和并行有什么区别,线程怎么创建,run()start() 有什么区别,线程有哪些状态,wait()sleep() 又差在哪里。

这些问题看起来碎,其实都在问一件事:一个任务从代码变成 CPU 上执行的指令,中间到底经历了什么。

进程和线程怎么区分

程序只是躺在磁盘上的文件。它要运行起来,就要把指令加载到 CPU,把数据加载到内存,还要管理文件、网络、磁盘这些资源。

这个正在运行的程序实例,就是进程。

线程则更轻。一个线程可以理解成一条指令流,它把自己的指令一条一条交给 CPU 执行。一个进程里面可以有一个线程,也可以有多个线程。
#mermaid-svg-Tst8ERo5Vs6zGoln{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Tst8ERo5Vs6zGoln .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Tst8ERo5Vs6zGoln .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Tst8ERo5Vs6zGoln .error-icon{fill:#552222;}#mermaid-svg-Tst8ERo5Vs6zGoln .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Tst8ERo5Vs6zGoln .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Tst8ERo5Vs6zGoln .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Tst8ERo5Vs6zGoln .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Tst8ERo5Vs6zGoln .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Tst8ERo5Vs6zGoln .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Tst8ERo5Vs6zGoln .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Tst8ERo5Vs6zGoln .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Tst8ERo5Vs6zGoln .marker.cross{stroke:#333333;}#mermaid-svg-Tst8ERo5Vs6zGoln svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Tst8ERo5Vs6zGoln p{margin:0;}#mermaid-svg-Tst8ERo5Vs6zGoln .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Tst8ERo5Vs6zGoln .cluster-label text{fill:#333;}#mermaid-svg-Tst8ERo5Vs6zGoln .cluster-label span{color:#333;}#mermaid-svg-Tst8ERo5Vs6zGoln .cluster-label span p{background-color:transparent;}#mermaid-svg-Tst8ERo5Vs6zGoln .label text,#mermaid-svg-Tst8ERo5Vs6zGoln span{fill:#333;color:#333;}#mermaid-svg-Tst8ERo5Vs6zGoln .node rect,#mermaid-svg-Tst8ERo5Vs6zGoln .node circle,#mermaid-svg-Tst8ERo5Vs6zGoln .node ellipse,#mermaid-svg-Tst8ERo5Vs6zGoln .node polygon,#mermaid-svg-Tst8ERo5Vs6zGoln .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Tst8ERo5Vs6zGoln .rough-node .label text,#mermaid-svg-Tst8ERo5Vs6zGoln .node .label text,#mermaid-svg-Tst8ERo5Vs6zGoln .image-shape .label,#mermaid-svg-Tst8ERo5Vs6zGoln .icon-shape .label{text-anchor:middle;}#mermaid-svg-Tst8ERo5Vs6zGoln .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Tst8ERo5Vs6zGoln .rough-node .label,#mermaid-svg-Tst8ERo5Vs6zGoln .node .label,#mermaid-svg-Tst8ERo5Vs6zGoln .image-shape .label,#mermaid-svg-Tst8ERo5Vs6zGoln .icon-shape .label{text-align:center;}#mermaid-svg-Tst8ERo5Vs6zGoln .node.clickable{cursor:pointer;}#mermaid-svg-Tst8ERo5Vs6zGoln .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Tst8ERo5Vs6zGoln .arrowheadPath{fill:#333333;}#mermaid-svg-Tst8ERo5Vs6zGoln .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Tst8ERo5Vs6zGoln .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Tst8ERo5Vs6zGoln .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Tst8ERo5Vs6zGoln .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Tst8ERo5Vs6zGoln .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Tst8ERo5Vs6zGoln .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Tst8ERo5Vs6zGoln .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Tst8ERo5Vs6zGoln .cluster text{fill:#333;}#mermaid-svg-Tst8ERo5Vs6zGoln .cluster span{color:#333;}#mermaid-svg-Tst8ERo5Vs6zGoln div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Tst8ERo5Vs6zGoln .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Tst8ERo5Vs6zGoln rect.text{fill:none;stroke-width:0;}#mermaid-svg-Tst8ERo5Vs6zGoln .icon-shape,#mermaid-svg-Tst8ERo5Vs6zGoln .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Tst8ERo5Vs6zGoln .icon-shape p,#mermaid-svg-Tst8ERo5Vs6zGoln .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Tst8ERo5Vs6zGoln .icon-shape .label rect,#mermaid-svg-Tst8ERo5Vs6zGoln .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Tst8ERo5Vs6zGoln .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Tst8ERo5Vs6zGoln .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Tst8ERo5Vs6zGoln :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 程序文件
进程
线程 1
线程 2
线程 3
独立内存空间 / IO 资源
共享进程内存

面试里可以这样说:

对比点 进程 线程
本质 正在运行的程序实例 进程内的一条执行路径
内存 不同进程通常有独立内存空间 同一进程内线程共享内存
切换成本 较高 较低
关系 一个进程可以包含多个线程 线程依附于进程存在

一句话总结就是:进程负责资源边界,线程负责执行路径。

并发和并行不是一回事

并发是同一时间段内应对多件事情,并行是同一时刻真正同时做多件事情。

单核 CPU 也能并发,因为操作系统会把 CPU 时间片分给不同线程。线程切换得很快,人看起来像同时执行,但微观上还是一个线程一个线程轮流跑。

多核 CPU 才能真正并行。比如 4 核 CPU 在某个时刻可以同时执行 4 个线程。
#mermaid-svg-kyakRkMqiYAvwjvX{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kyakRkMqiYAvwjvX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kyakRkMqiYAvwjvX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kyakRkMqiYAvwjvX .error-icon{fill:#552222;}#mermaid-svg-kyakRkMqiYAvwjvX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kyakRkMqiYAvwjvX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kyakRkMqiYAvwjvX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kyakRkMqiYAvwjvX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kyakRkMqiYAvwjvX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kyakRkMqiYAvwjvX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kyakRkMqiYAvwjvX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kyakRkMqiYAvwjvX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kyakRkMqiYAvwjvX .marker.cross{stroke:#333333;}#mermaid-svg-kyakRkMqiYAvwjvX svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kyakRkMqiYAvwjvX p{margin:0;}#mermaid-svg-kyakRkMqiYAvwjvX .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kyakRkMqiYAvwjvX .cluster-label text{fill:#333;}#mermaid-svg-kyakRkMqiYAvwjvX .cluster-label span{color:#333;}#mermaid-svg-kyakRkMqiYAvwjvX .cluster-label span p{background-color:transparent;}#mermaid-svg-kyakRkMqiYAvwjvX .label text,#mermaid-svg-kyakRkMqiYAvwjvX span{fill:#333;color:#333;}#mermaid-svg-kyakRkMqiYAvwjvX .node rect,#mermaid-svg-kyakRkMqiYAvwjvX .node circle,#mermaid-svg-kyakRkMqiYAvwjvX .node ellipse,#mermaid-svg-kyakRkMqiYAvwjvX .node polygon,#mermaid-svg-kyakRkMqiYAvwjvX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kyakRkMqiYAvwjvX .rough-node .label text,#mermaid-svg-kyakRkMqiYAvwjvX .node .label text,#mermaid-svg-kyakRkMqiYAvwjvX .image-shape .label,#mermaid-svg-kyakRkMqiYAvwjvX .icon-shape .label{text-anchor:middle;}#mermaid-svg-kyakRkMqiYAvwjvX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kyakRkMqiYAvwjvX .rough-node .label,#mermaid-svg-kyakRkMqiYAvwjvX .node .label,#mermaid-svg-kyakRkMqiYAvwjvX .image-shape .label,#mermaid-svg-kyakRkMqiYAvwjvX .icon-shape .label{text-align:center;}#mermaid-svg-kyakRkMqiYAvwjvX .node.clickable{cursor:pointer;}#mermaid-svg-kyakRkMqiYAvwjvX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kyakRkMqiYAvwjvX .arrowheadPath{fill:#333333;}#mermaid-svg-kyakRkMqiYAvwjvX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kyakRkMqiYAvwjvX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kyakRkMqiYAvwjvX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kyakRkMqiYAvwjvX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kyakRkMqiYAvwjvX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kyakRkMqiYAvwjvX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kyakRkMqiYAvwjvX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kyakRkMqiYAvwjvX .cluster text{fill:#333;}#mermaid-svg-kyakRkMqiYAvwjvX .cluster span{color:#333;}#mermaid-svg-kyakRkMqiYAvwjvX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kyakRkMqiYAvwjvX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kyakRkMqiYAvwjvX rect.text{fill:none;stroke-width:0;}#mermaid-svg-kyakRkMqiYAvwjvX .icon-shape,#mermaid-svg-kyakRkMqiYAvwjvX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kyakRkMqiYAvwjvX .icon-shape p,#mermaid-svg-kyakRkMqiYAvwjvX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kyakRkMqiYAvwjvX .icon-shape .label rect,#mermaid-svg-kyakRkMqiYAvwjvX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kyakRkMqiYAvwjvX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kyakRkMqiYAvwjvX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kyakRkMqiYAvwjvX :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 单核
多核
多个任务
CPU 核心数
时间片轮转
宏观看起来同时运行
并发
多个核心同时执行
并行

可以用一句很稳的面试话术:

并发强调处理多个任务的能力,并行强调同一时刻同时执行多个任务。单核 CPU 可以并发,多核 CPU 才能在物理上并行。

线程有哪些创建方式

PPT 里列了四种:

  1. 继承 Thread 类。
  2. 实现 Runnable 接口。
  3. 实现 Callable 接口,配合 FutureTask 拿返回值。
  4. 使用线程池创建线程。

继承 Thread 最直接:

java 复制代码
public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("MyThread...run...");
    }

    public static void main(String[] args) {
        new MyThread().start();
    }
}

实现 Runnable 更常见,因为任务和线程对象分开了:

java 复制代码
Runnable task = () -> System.out.println("running...");
new Thread(task, "t1").start();

CallableRunnable 多两个能力:有返回值,可以抛出异常。

java 复制代码
Callable<String> task = () -> {
    System.out.println(Thread.currentThread().getName());
    return "ok";
};

FutureTask<String> futureTask = new FutureTask<>(task);
new Thread(futureTask, "t1").start();
String result = futureTask.get();

但真实项目里,不建议频繁 new Thread()。更常见的方式是把任务交给线程池。

java 复制代码
ExecutorService threadPool = Executors.newFixedThreadPool(3);
threadPool.submit(() -> System.out.println("running..."));
threadPool.shutdown();

线程池这块后面会单独写一篇,因为它比"创建线程"复杂得多。

Runnable 和 Callable 有什么区别

这个问题很适合用表格回答:

对比点 Runnable Callable
方法 run() call()
返回值 没有返回值 有返回值
异常 不能向外抛受检异常 可以抛异常
获取结果 不支持 配合 Future / FutureTask

所以面试里不要只背"一个有返回值一个没有返回值"。更完整的回答是:

Runnable 更适合只执行任务、不关心结果的场景;Callable 更适合异步计算后还要拿结果或处理异常的场景。

run 和 start 有什么区别

run() 只是普通方法调用。

start() 才是真正启动一个新线程,让 JVM 创建线程并异步执行 run() 里的代码。

java 复制代码
Thread t1 = new Thread("t1") {
    @Override
    public void run() {
        System.out.println("running...");
    }
};

t1.start();

如果直接调用 t1.run(),代码仍然在当前线程里同步执行,不会创建新线程。

还有一个细节,start() 只能调用一次。对同一个线程对象重复调用 start(),会抛 IllegalThreadStateException
#mermaid-svg-ObM0FvDxoMTjGH3H{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ObM0FvDxoMTjGH3H .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ObM0FvDxoMTjGH3H .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ObM0FvDxoMTjGH3H .error-icon{fill:#552222;}#mermaid-svg-ObM0FvDxoMTjGH3H .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ObM0FvDxoMTjGH3H .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ObM0FvDxoMTjGH3H .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ObM0FvDxoMTjGH3H .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ObM0FvDxoMTjGH3H .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ObM0FvDxoMTjGH3H .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ObM0FvDxoMTjGH3H .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ObM0FvDxoMTjGH3H .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ObM0FvDxoMTjGH3H .marker.cross{stroke:#333333;}#mermaid-svg-ObM0FvDxoMTjGH3H svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ObM0FvDxoMTjGH3H p{margin:0;}#mermaid-svg-ObM0FvDxoMTjGH3H .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ObM0FvDxoMTjGH3H .cluster-label text{fill:#333;}#mermaid-svg-ObM0FvDxoMTjGH3H .cluster-label span{color:#333;}#mermaid-svg-ObM0FvDxoMTjGH3H .cluster-label span p{background-color:transparent;}#mermaid-svg-ObM0FvDxoMTjGH3H .label text,#mermaid-svg-ObM0FvDxoMTjGH3H span{fill:#333;color:#333;}#mermaid-svg-ObM0FvDxoMTjGH3H .node rect,#mermaid-svg-ObM0FvDxoMTjGH3H .node circle,#mermaid-svg-ObM0FvDxoMTjGH3H .node ellipse,#mermaid-svg-ObM0FvDxoMTjGH3H .node polygon,#mermaid-svg-ObM0FvDxoMTjGH3H .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ObM0FvDxoMTjGH3H .rough-node .label text,#mermaid-svg-ObM0FvDxoMTjGH3H .node .label text,#mermaid-svg-ObM0FvDxoMTjGH3H .image-shape .label,#mermaid-svg-ObM0FvDxoMTjGH3H .icon-shape .label{text-anchor:middle;}#mermaid-svg-ObM0FvDxoMTjGH3H .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ObM0FvDxoMTjGH3H .rough-node .label,#mermaid-svg-ObM0FvDxoMTjGH3H .node .label,#mermaid-svg-ObM0FvDxoMTjGH3H .image-shape .label,#mermaid-svg-ObM0FvDxoMTjGH3H .icon-shape .label{text-align:center;}#mermaid-svg-ObM0FvDxoMTjGH3H .node.clickable{cursor:pointer;}#mermaid-svg-ObM0FvDxoMTjGH3H .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ObM0FvDxoMTjGH3H .arrowheadPath{fill:#333333;}#mermaid-svg-ObM0FvDxoMTjGH3H .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ObM0FvDxoMTjGH3H .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ObM0FvDxoMTjGH3H .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ObM0FvDxoMTjGH3H .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ObM0FvDxoMTjGH3H .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ObM0FvDxoMTjGH3H .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ObM0FvDxoMTjGH3H .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ObM0FvDxoMTjGH3H .cluster text{fill:#333;}#mermaid-svg-ObM0FvDxoMTjGH3H .cluster span{color:#333;}#mermaid-svg-ObM0FvDxoMTjGH3H div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ObM0FvDxoMTjGH3H .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ObM0FvDxoMTjGH3H rect.text{fill:none;stroke-width:0;}#mermaid-svg-ObM0FvDxoMTjGH3H .icon-shape,#mermaid-svg-ObM0FvDxoMTjGH3H .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ObM0FvDxoMTjGH3H .icon-shape p,#mermaid-svg-ObM0FvDxoMTjGH3H .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ObM0FvDxoMTjGH3H .icon-shape .label rect,#mermaid-svg-ObM0FvDxoMTjGH3H .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ObM0FvDxoMTjGH3H .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ObM0FvDxoMTjGH3H .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ObM0FvDxoMTjGH3H :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} run()
start()
Thread 对象
调用方式
普通方法调用
当前线程执行
JVM 启动新线程
新线程执行 run()

线程有哪些状态

JDK 的 Thread.State 定义了六种状态:

状态 含义
NEW 新建,还没有调用 start()
RUNNABLE 可运行,可能正在运行,也可能等待 CPU 时间片
BLOCKED 等待获取 monitor 锁
WAITING 无限期等待,需要其他线程唤醒
TIMED_WAITING 限时等待,到时间或被唤醒后继续
TERMINATED 执行结束

状态流转可以这样看:
#mermaid-svg-6vV84wnyf1Zvly5C{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-6vV84wnyf1Zvly5C .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6vV84wnyf1Zvly5C .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6vV84wnyf1Zvly5C .error-icon{fill:#552222;}#mermaid-svg-6vV84wnyf1Zvly5C .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6vV84wnyf1Zvly5C .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6vV84wnyf1Zvly5C .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6vV84wnyf1Zvly5C .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6vV84wnyf1Zvly5C .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6vV84wnyf1Zvly5C .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6vV84wnyf1Zvly5C .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6vV84wnyf1Zvly5C .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6vV84wnyf1Zvly5C .marker.cross{stroke:#333333;}#mermaid-svg-6vV84wnyf1Zvly5C svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6vV84wnyf1Zvly5C p{margin:0;}#mermaid-svg-6vV84wnyf1Zvly5C defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-6vV84wnyf1Zvly5C g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-6vV84wnyf1Zvly5C g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-6vV84wnyf1Zvly5C g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-6vV84wnyf1Zvly5C g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-6vV84wnyf1Zvly5C g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-6vV84wnyf1Zvly5C .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-6vV84wnyf1Zvly5C .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-6vV84wnyf1Zvly5C .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-6vV84wnyf1Zvly5C .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-6vV84wnyf1Zvly5C .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-6vV84wnyf1Zvly5C .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-6vV84wnyf1Zvly5C .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-6vV84wnyf1Zvly5C .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6vV84wnyf1Zvly5C .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-6vV84wnyf1Zvly5C .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6vV84wnyf1Zvly5C .edgeLabel .label text{fill:#333;}#mermaid-svg-6vV84wnyf1Zvly5C .label div .edgeLabel{color:#333;}#mermaid-svg-6vV84wnyf1Zvly5C .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-6vV84wnyf1Zvly5C .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-6vV84wnyf1Zvly5C .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-6vV84wnyf1Zvly5C .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-6vV84wnyf1Zvly5C .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-6vV84wnyf1Zvly5C .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6vV84wnyf1Zvly5C .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6vV84wnyf1Zvly5C #statediagram-barbEnd{fill:#333333;}#mermaid-svg-6vV84wnyf1Zvly5C .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6vV84wnyf1Zvly5C .cluster-label,#mermaid-svg-6vV84wnyf1Zvly5C .nodeLabel{color:#131300;}#mermaid-svg-6vV84wnyf1Zvly5C .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-6vV84wnyf1Zvly5C .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-6vV84wnyf1Zvly5C .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-6vV84wnyf1Zvly5C .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-6vV84wnyf1Zvly5C .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-6vV84wnyf1Zvly5C .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-6vV84wnyf1Zvly5C .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-6vV84wnyf1Zvly5C .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-6vV84wnyf1Zvly5C .note-edge{stroke-dasharray:5;}#mermaid-svg-6vV84wnyf1Zvly5C .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-6vV84wnyf1Zvly5C .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-6vV84wnyf1Zvly5C .statediagram-note text{fill:black;}#mermaid-svg-6vV84wnyf1Zvly5C .statediagram-note .nodeLabel{color:black;}#mermaid-svg-6vV84wnyf1Zvly5C .statediagram .edgeLabel{color:red;}#mermaid-svg-6vV84wnyf1Zvly5C #dependencyStart,#mermaid-svg-6vV84wnyf1Zvly5C #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-6vV84wnyf1Zvly5C .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6vV84wnyf1Zvly5C :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} new Thread()
start()
等待 synchronized 锁
获得锁
wait() / join()
notify() / notifyAll()
sleep(ms) / wait(ms) / join(ms)
到时间或被唤醒
run() 执行结束
NEW
RUNNABLE
BLOCKED
WAITING
TIMED_WAITING
TERMINATED

有一个容易说错的点:Java 里的 RUNNABLE 包括操作系统层面的"就绪"和"运行"。所以线程进入 RUNNABLE,不代表它此刻一定正在占用 CPU。

join 怎么保证线程顺序执行

如果新建 T1T2T3 三个线程,要保证它们按顺序执行,可以用 join()

join() 的含义是:当前线程等待目标线程执行结束。

java 复制代码
Thread t1 = new Thread(() -> System.out.println("t1"));

Thread t2 = new Thread(() -> {
    try {
        t1.join();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
    System.out.println("t2");
});

Thread t3 = new Thread(() -> {
    try {
        t2.join();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
    System.out.println("t3");
});

t1.start();
t2.start();
t3.start();

线程 T3 线程 T2 线程 T1 线程 T3 线程 T2 线程 T1 #mermaid-svg-z1ORY3TCajBFzj16{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-z1ORY3TCajBFzj16 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-z1ORY3TCajBFzj16 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-z1ORY3TCajBFzj16 .error-icon{fill:#552222;}#mermaid-svg-z1ORY3TCajBFzj16 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-z1ORY3TCajBFzj16 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-z1ORY3TCajBFzj16 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-z1ORY3TCajBFzj16 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-z1ORY3TCajBFzj16 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-z1ORY3TCajBFzj16 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-z1ORY3TCajBFzj16 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-z1ORY3TCajBFzj16 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-z1ORY3TCajBFzj16 .marker.cross{stroke:#333333;}#mermaid-svg-z1ORY3TCajBFzj16 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-z1ORY3TCajBFzj16 p{margin:0;}#mermaid-svg-z1ORY3TCajBFzj16 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-z1ORY3TCajBFzj16 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-z1ORY3TCajBFzj16 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-z1ORY3TCajBFzj16 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-z1ORY3TCajBFzj16 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-z1ORY3TCajBFzj16 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-z1ORY3TCajBFzj16 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-z1ORY3TCajBFzj16 .sequenceNumber{fill:white;}#mermaid-svg-z1ORY3TCajBFzj16 #sequencenumber{fill:#333;}#mermaid-svg-z1ORY3TCajBFzj16 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-z1ORY3TCajBFzj16 .messageText{fill:#333;stroke:none;}#mermaid-svg-z1ORY3TCajBFzj16 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-z1ORY3TCajBFzj16 .labelText,#mermaid-svg-z1ORY3TCajBFzj16 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-z1ORY3TCajBFzj16 .loopText,#mermaid-svg-z1ORY3TCajBFzj16 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-z1ORY3TCajBFzj16 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-z1ORY3TCajBFzj16 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-z1ORY3TCajBFzj16 .noteText,#mermaid-svg-z1ORY3TCajBFzj16 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-z1ORY3TCajBFzj16 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-z1ORY3TCajBFzj16 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-z1ORY3TCajBFzj16 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-z1ORY3TCajBFzj16 .actorPopupMenu{position:absolute;}#mermaid-svg-z1ORY3TCajBFzj16 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-z1ORY3TCajBFzj16 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-z1ORY3TCajBFzj16 .actor-man circle,#mermaid-svg-z1ORY3TCajBFzj16 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-z1ORY3TCajBFzj16 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 执行任务join 等待 T1 结束T1 结束执行任务join 等待 T2 结束T2 结束执行任务

notify 和 notifyAll 有什么区别

notify()notifyAll() 都是唤醒在同一个对象监视器上 wait() 的线程。

区别很简单:

方法 效果
notify() 随机唤醒一个等待线程
notifyAll() 唤醒所有等待线程,让它们重新竞争锁

注意,唤醒不等于立刻执行。被唤醒的线程要先从 WAITING 回到可竞争状态,等当前线程释放锁之后,才能重新抢锁。

wait 和 sleep 有什么区别

这也是高频题,最好按三个维度回答。

对比点 wait sleep
所属类 Object 成员方法 Thread 静态方法
使用前提 必须先获得对象锁 不要求持有锁
是否释放锁 会释放对象锁 不会释放已持有的锁
唤醒方式 notify / notifyAll / 超时 / 中断 超时 / 中断

最关键的一句是:

wait 是对象监视器上的等待,会释放锁;sleep 只是让当前线程暂停一会儿,不会释放锁。
#mermaid-svg-y5nBhwDCpJEUBHi2{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-y5nBhwDCpJEUBHi2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-y5nBhwDCpJEUBHi2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-y5nBhwDCpJEUBHi2 .error-icon{fill:#552222;}#mermaid-svg-y5nBhwDCpJEUBHi2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-y5nBhwDCpJEUBHi2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-y5nBhwDCpJEUBHi2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-y5nBhwDCpJEUBHi2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-y5nBhwDCpJEUBHi2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-y5nBhwDCpJEUBHi2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-y5nBhwDCpJEUBHi2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-y5nBhwDCpJEUBHi2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-y5nBhwDCpJEUBHi2 .marker.cross{stroke:#333333;}#mermaid-svg-y5nBhwDCpJEUBHi2 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-y5nBhwDCpJEUBHi2 p{margin:0;}#mermaid-svg-y5nBhwDCpJEUBHi2 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-y5nBhwDCpJEUBHi2 .cluster-label text{fill:#333;}#mermaid-svg-y5nBhwDCpJEUBHi2 .cluster-label span{color:#333;}#mermaid-svg-y5nBhwDCpJEUBHi2 .cluster-label span p{background-color:transparent;}#mermaid-svg-y5nBhwDCpJEUBHi2 .label text,#mermaid-svg-y5nBhwDCpJEUBHi2 span{fill:#333;color:#333;}#mermaid-svg-y5nBhwDCpJEUBHi2 .node rect,#mermaid-svg-y5nBhwDCpJEUBHi2 .node circle,#mermaid-svg-y5nBhwDCpJEUBHi2 .node ellipse,#mermaid-svg-y5nBhwDCpJEUBHi2 .node polygon,#mermaid-svg-y5nBhwDCpJEUBHi2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-y5nBhwDCpJEUBHi2 .rough-node .label text,#mermaid-svg-y5nBhwDCpJEUBHi2 .node .label text,#mermaid-svg-y5nBhwDCpJEUBHi2 .image-shape .label,#mermaid-svg-y5nBhwDCpJEUBHi2 .icon-shape .label{text-anchor:middle;}#mermaid-svg-y5nBhwDCpJEUBHi2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-y5nBhwDCpJEUBHi2 .rough-node .label,#mermaid-svg-y5nBhwDCpJEUBHi2 .node .label,#mermaid-svg-y5nBhwDCpJEUBHi2 .image-shape .label,#mermaid-svg-y5nBhwDCpJEUBHi2 .icon-shape .label{text-align:center;}#mermaid-svg-y5nBhwDCpJEUBHi2 .node.clickable{cursor:pointer;}#mermaid-svg-y5nBhwDCpJEUBHi2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-y5nBhwDCpJEUBHi2 .arrowheadPath{fill:#333333;}#mermaid-svg-y5nBhwDCpJEUBHi2 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-y5nBhwDCpJEUBHi2 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-y5nBhwDCpJEUBHi2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-y5nBhwDCpJEUBHi2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-y5nBhwDCpJEUBHi2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-y5nBhwDCpJEUBHi2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-y5nBhwDCpJEUBHi2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-y5nBhwDCpJEUBHi2 .cluster text{fill:#333;}#mermaid-svg-y5nBhwDCpJEUBHi2 .cluster span{color:#333;}#mermaid-svg-y5nBhwDCpJEUBHi2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-y5nBhwDCpJEUBHi2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-y5nBhwDCpJEUBHi2 rect.text{fill:none;stroke-width:0;}#mermaid-svg-y5nBhwDCpJEUBHi2 .icon-shape,#mermaid-svg-y5nBhwDCpJEUBHi2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-y5nBhwDCpJEUBHi2 .icon-shape p,#mermaid-svg-y5nBhwDCpJEUBHi2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-y5nBhwDCpJEUBHi2 .icon-shape .label rect,#mermaid-svg-y5nBhwDCpJEUBHi2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-y5nBhwDCpJEUBHi2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-y5nBhwDCpJEUBHi2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-y5nBhwDCpJEUBHi2 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} wait()
sleep(ms)
线程持有锁
调用方法
释放锁
进入 WAITING / TIMED_WAITING
被 notify 或超时后重新竞争锁
不释放锁
进入 TIMED_WAITING
时间到后继续执行

如何停止一个正在运行的线程

不要用 Thread.stop()。它已经被废弃,因为它会粗暴终止线程,可能导致锁释放和数据状态都不可靠。

常见做法有两种:

  1. 使用退出标记,让线程自己在合适的位置结束。
  2. 使用 interrupt() 中断线程,由线程自己决定如何响应。

阻塞中的线程,比如正在 sleep()wait()join(),收到中断后会抛 InterruptedException

普通运行中的线程,interrupt() 不会强行停止它,只是把中断标记设置为 true。线程需要自己检查这个标记。

java 复制代码
Thread worker = new Thread(() -> {
    while (!Thread.currentThread().isInterrupted()) {
        // do work
    }
});

worker.start();
worker.interrupt();

这也是并发编程里很重要的思想:停止线程不是外部强杀,而是协作式退出。

面试怎么答

如果面试官从基础题开始问,可以把回答组织成一条线:

线程是进程内的执行路径,同一进程内的线程共享内存,所以多线程能提升吞吐,也会带来线程安全问题。

并发是多个任务交替推进,并行是多个任务同一时刻同时执行。Java 里创建线程可以继承 Thread、实现 Runnable、实现 Callable 或使用线程池,项目里更推荐线程池。

线程启动要调用 start(),直接调用 run() 只是普通方法调用。线程状态主要有 NEWRUNNABLEBLOCKEDWAITINGTIMED_WAITINGTERMINATED。其中 wait() 会释放锁,sleep() 不会释放锁。停止线程时不建议用 stop(),更推荐退出标记或 interrupt() 这种协作式方式。

相关推荐
sugar__salt1 小时前
JS正则表达式与字符串高阶实战精讲
开发语言·javascript·正则表达式
AI浩1 小时前
梯度累积与 Micro-Batch 设计分层式精讲:有效批次、显存边界与分布式同步
开发语言·分布式·batch
未若君雅裁1 小时前
死锁产生条件与诊断:jps、jstack、VisualVM
java·开发语言
再玩一会儿看代码1 小时前
Java抽象类和接口区别_场景理解
java·开发语言·经验分享·笔记·python
用户925807911481 小时前
画图理解mysql日志机制
java·后端
javahongxi1 小时前
Spring Cloud Trace 链路实现
java·spring boot·spring cloud
海梨花1 小时前
腾讯面试高频算法题
java·算法·面试
于先生吖1 小时前
Java消息队列优化抢单逻辑,同城搬家拉货多场景业务数据库架构设计
java·开发语言·数据库架构
半个烧饼不加肉1 小时前
JS 底层探究--执行上下文
开发语言·前端·javascript