You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

若将线程全部功能放在start方法而非run方法中,会有何影响?

把线程逻辑放在start()而非run()里会发生什么?

嘿,这个问题问到点子上了!咱们先从Thread类的核心逻辑说起,再拆解你这段代码的“假象”。

先搞懂Thread.start()的原生作用

Thread类的start()方法核心职责是启动一个全新的执行线程:它会调用底层native方法向操作系统申请创建新线程,当新线程初始化完成后,才会在这个新线程的上下文里调用run()方法。

换句话说,start()是“启动线程的开关”,而run()才是“线程要执行的任务逻辑容器”。

你的代码为什么看起来“效果一致”?

先看你这段代码:

public class RunMethodTest extends AppCompatActivity { 
    @Override protected void onCreate(@Nullable Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        Abc abc=new Abc(); 
        abc.start(); 
    } 
} 

class Abc extends Thread { 
    @Override public synchronized void start() { 
        super.start(); // 调用原生start(),确实启动了新线程
        // 注意:下面的循环是在调用start()的线程(主线程)里执行的!
        for(int i=0;i<10;i++) { 
            try { 
                Thread.sleep(1000); 
            } catch (InterruptedException e) { 
                e.printStackTrace(); 
            } 
            System.out.println("Thread" + " " + i); 
        } 
    } 
}

你在重写的start()里先调用了super.start(),这一步确实启动了新线程,但关键是:后面的for循环是在调用abc.start()的主线程中执行的,而非新线程!

之所以看起来和把代码放run()里效果一样,是因为你的新线程根本没干活——你没重写run()方法,原生Thread的run()是空实现,所以新线程启动后立刻就结束了。你看到的所有打印,其实都是主线程在阻塞执行sleep和打印操作。

本质差异到底在哪?

咱们对比两种写法的核心区别:

  • 把循环放在run()里:循环逻辑会在super.start()创建的新线程中执行,主线程调用abc.start()后会立刻回到onCreate()继续执行后续代码(不会被sleep阻塞),两个线程并行运行。
  • 把循环放在start()里:循环逻辑是在主线程执行的,主线程会被sleep阻塞10秒,直到循环完成才会继续走onCreate()的后续逻辑;而新线程启动后啥也不做,直接结束。

你可以做个小测试验证:在abc.start()后面加一句System.out.println("主线程继续执行"),看输出顺序:

  • 放在run()里:会先打印“主线程继续执行”,然后每隔1秒打印子线程的内容;
  • 放在start()里:会先每隔1秒打印循环内容,10秒后才会打印“主线程继续执行”。

总结

永远别把线程的任务逻辑放在start()里!start()的唯一职责就是启动新线程,把任务逻辑放在run()里,才是符合Thread设计规范的正确做法。

内容的提问来源于stack exchange,提问作者varmashrivastava

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:44:59