若将线程全部功能放在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
相关产品推荐
相关产品推荐

