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

相关推荐
始持1 分钟前
第十三讲 异步操作与异步构建
前端·flutter
后端AI实验室1 分钟前
我让AI模拟面试官考了我一个小时,然后我沉默了
java·ai
金銀銅鐵8 分钟前
Byte Buddy 生成的类的结构如何?(第二篇)
java·后端
StackNoOverflow8 分钟前
Spring MVC零散知识点记录
java·spring·mvc
几许8 分钟前
高并发有序顺序号生成中间件 - 架构设计文档
java·后端
几许9 分钟前
高并发强一致性顺序号生成系统 -- SequenceGenerator
java·github
闻哥10 分钟前
深入理解 MySQL InnoDB Buffer Pool 的 LRU 冷热数据机制
android·java·jvm·spring boot·mysql·adb·面试
xiangpanf11 分钟前
PHP vs C语言:30字解析两大编程语言差异
c语言·开发语言·php
wdfk_prog12 分钟前
MAX14830 可移植 C 驱动实现分析:一个适合多串口扩展场景的开源基础版本
c语言·开发语言·开源