Thread的run()和start()的区别

本文介绍了Java线程的基础知识,包括线程的创建、启动及五种基本状态。同时,详细阐述了实现线程的两种常见方式:继承Thread类与实现Runnable接口。

java线程是通过java.lang.Thread类来实现的,JVM启动时会有一个由主方法所定义的线程,可以通过创建Thread类的实例来创建线程,每个线程都是通过某个特定的Thread类对象对应的run()方法来实现的,run()方法称为线程体。通过调用start()方法来启动一个线程。



java中线程通常有五种状态,创建,就绪,运行,阻塞,死亡

       第一是创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。
  第二是就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。
  第三是运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
  第四是阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。
  第五是死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪。


实现并启动线程的两种方式

        1.写一个类继承自Thread类,重写run()方法。用start()启动线程

         2.写一个类继承自Runnable接口,实现run()方法。用new Thread(Runnable target).start()方法来启动。



1.start()方法来启动线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码;通过调用Thread类的start()方法来启动一个线程, 这时此线程是处于就绪状态, 并没有运行。 然后通过此Thread类调用方法run()来完成其运行操作的, 这里方法run()称为线程体,它包含了要执行的这个线程的内容, Run方法运行结束, 此线程终止。然后CPU再调度其它线程。

2.run()方法当作普通方法的方式调用。程序还是要顺序执行,要等待run方法体执行完毕后,才可继续执行下面的代码; 程序中只有主线程——这一个线程, 其程序执行路径还是只有一条, 这样就没有达到写线程的目的。

记住:多线程就是分时利用CPU,宏观上让所有线程一起执行 ,也叫并发


[java]  view plain  copy
 print ?
  1. public class Test {  
  2.     public static void main(String[] args) {  
  3.         Runner1 runner1 = new Runner1();  
  4.         Runner2 runner2 = new Runner2();  
  5. //      Thread(Runnable target) 分配新的 Thread 对象。  
  6.         Thread thread1 = new Thread(runner1);  
  7.         Thread thread2 = new Thread(runner2);  
  8. //      thread1.start();  
  9. //      thread2.start();  
  10.         thread1.run();  
  11.         thread2.run();  
  12.     }  
  13. }  
  14.   
  15. class Runner1 implements Runnable { // 实现了Runnable接口,jdk就知道这个类是一个线程  
  16.     public void run() {  
  17.         for (int i = 0; i < 100; i++) {  
  18.             System.out.println("进入Runner1运行状态——————————" + i);  
  19.         }  
  20.     }  
  21. }  
  22.   
  23. class Runner2 implements Runnable { // 实现了Runnable接口,jdk就知道这个类是一个线程  
  24.     public void run() {  
  25.         for (int i = 0; i < 100; i++) {  
  26.             System.out.println("进入Runner2运行状态==========" + i);  
  27.         }  
  28.     }  
  29. }  


<think>首先,用户的问题是:“我想了解thread.startthread.run区别 请问thread.startthread.run区别”。这是在询问Java中Thread类的start()run()方法的区别。 从系统级指令中,我有几个关键点: - 所有行内数学表达式必须使用$...$格式。 - 独立公式必须使用$$...$$格式并单独成段。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,如[^1]。 - 结构清晰,逐步解决问题。 我需要参考提供的站内引用: - 引用[1]:讨论了Java中Threadstart()run()区别,强调start()启动线程,run()只是调用方法。 - 引用[2]:关于C#中Task.RunTask.Factory.StartNew的区别,但这是C#相关的,用户的问题是Java,所以我应该谨慎使用。 - 引用[3]:也是C#相关的,类似Task.RunTask.Factory.StartNew。 - 引用[4]:解释了Thread.start()run()区别及原理,提到Runnable接口、线程状态等。 用户的问题是针对Java的Thread类,所以我应该主要基于引用[1][4],因为它们直接相关。引用[2][3]是C#的,可能不适合Java上下文,但可以类比理解概念。 核心区别: - start()方法:启动一个新线程,使线程进入就绪状态,然后JVM调用run()方法在新线程中执行。 - run()方法:只是一个普通方法调用。如果直接调用run(),它会在当前线程中执行,而不是创建新线程。 从引用[1]:"t.start(); 该行代码相当于是启动线程,t.run(); 该行代码相当于是使用t这个类中的run方法而已." 从引用[4]:"Thread.start()启动线程,然后调用run()方法。直接调用run()不会创建新线程。" 结构清晰回答: 1. **引言**:简要解释方法它们的作用。 2. **关键区别**:对比start()run()的行为。 3. **示例**:提供一个简单的Java代码示例来演示区别。 4. **原理**:解释线程状态为什么start()会创建新线程。 5. **结论**:总结何时使用哪个。 6. **生成相关问题**:在回答末尾添加相关问题。 使用中文回答: - 整个回答需要用中文。 生成相关问题: - 我应该添加3-4个相关问题,类似于示例中的格式。 - 例如: 1. 如何在Java中创建线程的其他方式? 2. 线程状态有哪些? 3. 为什么直接调用run()不是推荐的做法? 4. Runnable接口Thread类的关系? 引用标识: - 在引用内容末尾添加[^1]、[^2]等。但用户提供的引用不是直接可用的源,所以我需要基于内容自然地添加引用。例如,如果我从引用[1]中借用观点,就加[^1]。 确保LaTeX正确: - 用户的问题没有涉及数学表达式,所以可能不需要使用LaTeX。但如果提到任何公式或代码,确保格式正确。 - 代码块应该像示例中一样使用```格式。 完整回答结构: - 先解释start()方法。 - 然后解释run()方法。 - 对比区别。 - 代码示例。 - 相关问题。 最终输出应包括: - 清晰的中文解释。 - 代码示例(如果需要)。 - 引用标识。 - 相关问题部分。 </think>### Thread.start() Thread.run()区别 在Java多线程编程中,`Thread.start()` `Thread.run()` 是两个关键方法,它们的行为用途有本质区别。理解这些区别对于正确使用线程至关重要。下面我将逐步解释它们的区别、原理实际影响。 1. **方法作用行为区别** - **`Thread.start()`**: 此方法用于启动一个新线程。当你调用 `start()` 时,Java虚拟机(JVM)会创建一个新的执行线程,并使该线程进入就绪状态。随后,JVM会自动调用该线程的 `run()` 方法在新线程中执行代码。这个过程涉及线程调度生命周期管理,是异步操作。 - 例如:`t.start()` 会创建一个新线程并行运行代码[^1]。 - 线程状态变化:调用 `start()` 后,线程从新建状态(NEW)转移到就绪状态(RUNNABLE),最终由调度器分配到运行状态(RUNNING)[^4]。 - **`Thread.run()`**: 此方法只是一个普通的成员方法,不涉及线程创建。直接调用 `run()` 会在当前线程中同步执行代码,就像调用任何其他方法一样。它不会创建新线程,如果用于多线程场景,会导致代码串行运行,失去了多线程的并行优势。 - 例如:`t.run()` 只是执行 `run()` 方法的内容,不会启动新线程[^1]。 - 常见错误:许多初学者误以为调用 `run()` 能启动线程,但实际只是普通方法调用[^4]。 2. **关键区别总结** | 特性 | `Thread.start()` | `Thread.run()` | |-------------------|--------------------------------------------|------------------------------------------| | **线程创建** | 创建新线程并行执行代码 | 无新线程,代码在当前线程同步执行 | | **并发性** | 支持并发,提高程序效率 | 无并发效果,代码顺序执行 | | **适用场景** | 需要异步任务时(如后台计算或IO操作) | 仅用于测试或调试,不建议在生产代码中使用 | | **线程状态管理** | 触发线程生命周期变化(就绪→运行→终止) | 不影响线程状态,只是方法执行 | | **性能影响** | 涉及线程调度开销,但能充分利用多核CPU | 无额外开销,但无法利用多线程优势 | 简单来说,`start()` 是“点火器”,启动新线程;而 `run()` 是“引擎”,只包含要运行的代码逻辑[^1][^4]。 3. **代码示例演示** 下面通过一个Java示例直观展示区别: ```java public class ThreadDemo extends Thread { @Override public void run() { System.out.println("当前线程: " + Thread.currentThread().getName()); } public static void main(String[] args) { ThreadDemo t = new ThreadDemo(); // 调用 run():在当前线程(main)中执行 t.run(); // 输出: "当前线程: main" // 调用 start():在新线程中执行 t.start(); // 输出类似: "当前线程: Thread-0" } } ``` - **输出分析**: - `t.run()` 的输出线程名是 `main`,表示在主线程中运行。 - `t.start()` 的输出线程名是 `Thread-0`,表示在新创建的线程中运行。 这证明了 `start()` 创建新线程,而 `run()` 只是方法调用[^1]。 4. **原理底层机制** - **`start()` 的工作流程**: - 当调用 `start()` 时,JVM 会调用底层操作系统的线程创建API(如POSIX线程),创建一个新线程。 - 新线程被添加到线程池调度队列,由JVM调度器管理其执行。 - 线程启动后,自动调用 `run()` 方法执行任务。 - 如果多次调用 `start()` (线程已启动),会抛出 `IllegalThreadStateException`。 - **为什么 `run()` 不创建线程**: - `run()` 方法定义在 `Runnable` 接口中(Thread实现了该接口),只是一个任务定义方法。 - 直接调用 `run()` 不会触发JVM的线程管理逻辑,而是像普通方法一样由调用者线程执行。 - 通过 `Runnable` 接口,Java实现了线程逻辑与线程创建的分离,避免强制继承Thread类[^4]。 5. **最佳实践注意事项** - **何时使用 `start()`**: - 需要并行执行任务时(如并发下载、实时数据处理)。 - 在GUI应用中防止主线程阻塞。 - **何时避免 `run()`**: - 永远不要在多线程场景中直接调用 `run()`,因为它会导致程序失去并发性。 - 仅在调试时使用,例如测试 `run()` 方法逻辑是否正确。 - **常见错误**: - 误用 `run()` 导致“伪多线程”,即代码看似多线程但实际串行执行。 - 忘记调用 `start()` 而直接调用 `run()`,使线程无法启动。 总之,`Thread.start()` 是启动新线程的标准方式,启用并行执行;`Thread.run()` 只是执行代码块的方法,不涉及线程创建。正确使用 `start()` 能提升程序效率响应性[^1][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值