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() :输出的线程名会变

相关推荐
CHANG_THE_WORLD2 分钟前
<Fluent Python > Unicode 文本与字节
开发语言·python
AI人工智能+电脑小能手7 分钟前
【大白话说Java面试题】【Java基础篇】第20题:HashMap在计算index的时候,为什么要对数组长度做减1操作
java·开发语言·数据结构·后端·面试·哈希算法·hash-index
凯瑟琳.奥古斯特8 分钟前
Bootstrap快速上手指南
开发语言·前端·css·bootstrap·html
嵌入式×边缘AI:打怪升级日志10 分钟前
嵌入式Linux开发(了解交叉编译工具链的组成)
java·linux·运维
精益数智工坊13 分钟前
拆解制造业仓库物料管理流程:如何通过标准化仓库物料管理流程解决账实不符难题
大数据·前端·数据库·人工智能·精益工程
恶猫17 分钟前
网页自动化模拟操作时,模拟真实按键触发事件【终级方案】
前端·javascript·自动化·vue·网页模拟
FreeGo~19 分钟前
Linux 系统编程 进程篇 (五)
java·linux·服务器
我就是妖怪21 分钟前
Kimi K2.6 智能效果实测与能力全景展示
开发语言
中二痞24 分钟前
下载Python 版本,环境变量变更以及PyCharm更换python版本
开发语言·python·pycharm
故事和你9126 分钟前
洛谷-算法2-3-分治与倍增5
开发语言·数据结构·c++·算法·动态规划·图论