面试被问线程两次 start,我直接尬住了

本引用仅用学习,禁用商用
引用自 https://mp.weixin.qq.com/s/fJsYrkBIN6QEK_Xwzsz0eg

 

记得是一个周末,我去面 Java 后端开发岗。面试官上来就猛攻多线程知识,从创建方式到锁机制,一连串问题砸来。还好我提前背了八股文,所以七七八八的也答上来了。

本以为快结束能松口气,面试官冷不丁问:“看过 Thread 源码吗?” 我毫不犹豫的回答看过,紧接着他问:

线程在调用了一次start启动后,再调用一次可以不?如果线程执行完,同样再调用一次start又会怎么样?

当时我支支吾吾,没能答上来。面试结束后,我仔细研究了这个问题,并整理了相关知识点,希望能帮到同样遇到这个难题的朋友。

1. start() 方法的作用

在 Java 中,start() 方法是用来启动线程的。调用 start() 后,JVM 会创建一个新的线程,并执行 run() 方法中的代码。

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("线程正在运行...");
        });
        System.out.println(thread.getName() + ":" + thread.getState());
        thread.start();
        System.out.println(thread.getName() + ":" + thread.getState());
    }
}

  输出:

Thread-0:NEW
Thread-0:RUNNABLE
线程正在运行...

当我们创建一个Thread实例时,线程处于NEW(新建)状态。此时,调用start()方法会让线程进入RUNNABLE(可运行) 状态,等待CPU调度执行。

这里也补充一个小的知识点:

 

网上很多八股文面试题中说Java创建线程的方式有3种、4种,或者更多种。准确来说,创建线程只有一种方式那就是:new Thread().start()。

那线程调用两次 start()会发生什么?别急,我们接着看。

2. 调用两次 start()会发生什么?

先来看一段代码:

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("线程正在运行...");
        });
        System.out.println(thread.getName() + ":" + thread.getState());
        thread.start();
        System.out.println(thread.getName() + ":" + thread.getState());
        thread.start();
        System.out.println(thread.getName() + ":" + thread.getState());
    }
}

 

输出:

 

第二次调用时,代码抛出IllegalThreadStateException异常。

这是为什么呢?我们跟进start源码中一探究竟!

 

3. start() 方法的源码分析

以下是 Thread 类中 start() 方法的源码(基于 JDK 1.8):

public class Main {
    public synchronized void start() {
        // 检查线程状态
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        // 将线程添加到线程组
        group.add(this);
        boolean started = false;
        try {
            // 调用本地方法启动线程
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {            
                // 忽略异常
            }
        }
    }
}

  

关键点:

  • 状态检查:threadStatus 是线程的内部状态标志。若它不等于0表示线程已经启动或结束,直接抛IllegalThreadStateException异常。
  • 状态转换:start0() 是一个本地方法(Native Method),由 JVM 实现,负责真正启动线程。调用 start0() 后,线程进入就绪(RUNNABLE) 状态,等待 CPU 调度。

4. 总结

通过前面的分析,相信大家已经明白了:start() 方法只能调用一次。如果尝试调用两次,程序会抛出 IllegalThreadStateException 异常。

这是因为线程的生命周期是单向的,从创建(NEW)到运行(RUNNABLE),再到终止(TERMINATED)。一旦线程开始执行,它的状态会逐步推进,最终结束,无法回退。




















 

posted @ 2025-05-25 21:47  IT6889  阅读(22)  评论(0)    收藏  举报