Thread类中run和start的区别

我们先看一个简单例子

java 复制代码
public class SimpleExample {
    public static void main(String[] args) {
        System.out.println("=== 故事开始 ===");
        
        // 创建一个"唱歌"任务
        Thread singThread = new Thread(() -> {
            System.out.println("[唱歌线程] 开始唱歌...");
            try {
                Thread.sleep(3000); // 唱3秒钟
            } catch (Exception e) {}
            System.out.println("[唱歌线程] 唱完歌了");
        });
        
        System.out.println("\n--- 第1次测试:用run() ---");
        System.out.println("[主线程] 调用singThread.run()");
        singThread.run();  // 调用run()
        System.out.println("[主线程] run()调用完毕");
        
        System.out.println("\n--- 第2次测试:用start() ---");
        // 重新创建线程(因为一个Thread对象只能start一次)
        singThread = new Thread(() -> {
            System.out.println("[唱歌线程] 开始唱歌...");
            try {
                Thread.sleep(3000);
            } catch (Exception e) {}
            System.out.println("[唱歌线程] 唱完歌了");
        });
        
        System.out.println("[主线程] 调用singThread.start()");
        singThread.start();  // 调用start()
        System.out.println("[主线程] start()调用完毕");
        
        // 主线程等一会儿,看看效果
        try {
            Thread.sleep(5000);
        } catch (Exception e) {}
        System.out.println("\n=== 故事结束 ===");
    }
}

运行结果对比

=== 故事开始 ===

--- 第1次测试:用run() ---

主线程 调用singThread.run()

唱歌线程 开始唱歌...

(这里会卡住3秒钟,因为Thread.sleep(3000))

唱歌线程 唱完歌了

主线程 run()调用完毕

--- 第2次测试:用start() ---

主线程 调用singThread.start()

主线程 start()调用完毕 ← 注意!这里立即输出,没有等待!

唱歌线程 开始唱歌...

(这里主线程继续运行,唱歌在后台进行)

=== 故事结束 ===

唱歌线程 唱完歌了 ← 可能在这里输出,因为唱得慢

最关键的区别

  1. 卡不卡的区别
  • 用run() :程序会卡住3秒 ,因为Thread.sleep(3000)在当前线程执行

  • 用start() :程序不卡,主线程继续运行,唱歌在后台慢慢唱

  1. 顺序的区别
  • 用run():一定是这个顺序:

    1. "唱歌线程 开始唱歌..."

    2. (等待3秒)

    3. "唱歌线程 唱完歌了"

    4. "主线程 run()调用完毕"

  • 用start():顺序不确定,可能是:

    1. "主线程 start()调用完毕" ← 先输出!

    2. "唱歌线程 开始唱歌..." ← 后输出

      或者反过来,因为两个线程同时运行

再看一个简单的例子

public class MostSimple {

public static void main(String\[\] args) throws Exception {

Thread t = new Thread(() -> {

System.out.println("我是新线程,我的名字是:" + Thread.currentThread().getName());

});

System.out.println("主线程名字:" + Thread.currentThread().getName());

System.out.println("\n--- 用run() ---");

t.run(); // 注意看输出的线程名!

System.out.println("\n--- 用start() ---");

t.start();

Thread.sleep(100); // 等新线程执行完

}

}

运行结果:

主线程名字:main

--- 用run() ---

我是新线程,我的名字是:main ← 注意!还是main线程!

--- 用start() ---

我是新线程,我的名字是:Thread-0 ← 看!线程名变了!

run() = 你自己干活(当前线程执行代码)
start() = 叫别人干活(创建新线程执行代码)

总结:

  1. 用run() :代码在当前线程执行,会卡住当前线程

  2. 用start() :代码在新线程执行,不卡当前线程

  3. 用run() :输出的线程名不变

  4. 用start() :输出的线程名会变

相关推荐
兰令水3 分钟前
leecodecode【面试150】【2026.6.14打卡-java版本】
java·算法·面试
JustHappy6 小时前
古法编程秘籍(七):互联网到底是什么?把两台电脑怎么说话搞懂就够了
前端·后端·网络协议
snow@li6 小时前
SEO-文章标题:写文章时候,分类+主标题+大纲+解释 作为标题 / 不点进去也知道全文覆盖什么 / 标题即架构
前端
yaoxin5211236 小时前
434. Java 日期时间 API - Period 基于日期的时间段
java·开发语言·python
凡人叶枫7 小时前
Effective C++ 条款30:透彻了解 inlining 的里里外外
linux·开发语言·c++·嵌入式开发·effective c++
学逆向的7 小时前
C++纯虚函数
开发语言·c++·网络安全
kyriewen7 小时前
Git Commit 前自动修复代码风格?配置 Husky + lint-staged,从此 CR 只聊逻辑
前端·git·面试
何极光7 小时前
IDEA集成Maven
java·maven·intellij-idea
小和尚同志7 小时前
AI 自动化测试探索(一):Playwright MCP
前端·人工智能·aigc
程序员二叉8 小时前
【JUC】ThreadLocal底层原理|内存泄漏|弱引用|跨线程传递方案
java·开发语言·面试·职场和发展·juc