Java中为什么start方法不能重复调用而run方法可以?

作者:??Java中文社群???? 时间:2023-11-15 03:04:02 

初学线程时,总是将 run 方法和 start 方法搞混,虽然二者是完全不同的两个方法,但刚开始使用时很难分清,原因就是因为初次使用时效果貌似是一样的,

如下代码所示:

public static void main(String[] args) {
   // 创建线程一
   Thread thread = new Thread(new Runnable() {
       @Override
       public void run() {
           System.out.println("执行线程一");
       }
   });
   // 调用 run 方法
   thread.run();

// 创建线程二
   Thread thread2 = new Thread(new Runnable() {
       @Override
       public void run() {
           System.out.println("执行线程二");
       }
   });
   // 调用 start 方法
   thread2.start();
}

以上程序的执行结果如下: 

Java中为什么start方法不能重复调用而run方法可以?

 从上述结果可以看出,二者调用之后的执行效果都是一样,都可以成功执行任务。但是,如果在执行线程的时候,加上打印当前线程的名称就能看出二者的不同了,

如下代码所示:

public static void main(String[] args) {
   // 创建线程一
   Thread thread = new Thread(new Runnable() {
       @Override
       public void run() {
           // 获取到当前执行线程
           Thread currThread = Thread.currentThread();
           System.out.println("执行线程一,线程名:" + currThread.getName());
       }
   });
   // 调用 run 方法
   thread.run();

// 创建线程二
   Thread thread2 = new Thread(new Runnable() {
       @Override
       public void run() {
           // 获取到当前执行线程
           Thread currThread = Thread.currentThread();
           System.out.println("执行线程二,线程名:" + currThread.getName());
       }
   });
   // 调用 start 方法
   thread2.start();
}

以上程序的执行结果如下: 

Java中为什么start方法不能重复调用而run方法可以?

 从上述结果我们可以看出:当调用 run 方法时,其实是调用当前主程序 main 来执行方法体的;而调用 start 方法才是真正的创建一个新线程来执行任务。

区别1

run 方法和 start 方法的第一个区别是:调用 start 方法是真正开启一个线程来执行任务,而调用 run 方法相当于执行普通方法 run,并不会开启新线程,

如下图所示: 

Java中为什么start方法不能重复调用而run方法可以?

区别2

run 方法和 start 方法的第二个区别是:run 方法也叫做线程体,它里面包含了具体要执行的业务代码,当调用 run 方法时,会立即执行 run 方法中的代码(如果当前线程时间片未用完);而调用 start 方法时,是启动一个线程并将线程的状态设置为就绪状态。也就是说调用 start 方法,并不会立即执行。

区别3

因为 run 方法是普通方法,而普通方法是可以被多次调用的,所以 run 方法可以被调用多次;而 start 方法是创建新线程来执行任务,因为线程只能被创建一次,所以它们的第三个区别是:run 方法可以被调用多次,而 start 方法只能被调用一次。

 测试代码如下:

// 创建线程一
Thread thread = new Thread(new Runnable() {
   @Override
   public void run() {
       // 获取到当前执行的线程
       Thread currThread = Thread.currentThread();
       System.out.println("执行线程一,线程名:" + currThread.getName());
   }
});
// 调用 run 方法
thread.run();
// 多次调用 run 方法
thread.run();

// 创建线程二
Thread thread2 = new Thread(new Runnable() {
   @Override
   public void run() {
       // 获取到当前执行的线程
       Thread currThread = Thread.currentThread();
       System.out.println("执行线程二,线程名:" + currThread.getName());
   }
});
// 调用 start 方法
thread2.start();
// 多次调用 start 方法
thread2.start();

以上程序的执行结果如下: 

Java中为什么start方法不能重复调用而run方法可以?

 从上述结果可以看出,run 方法多次调用可用正常执行,而第二次调用 start 方法时程序就报错了,提示“IllegalThreadStateException”非法线程状态异常。

为什么start不能被重复调用?

要找到这个问题的答案,就要查看 start 方法的实现源码,它的源码如下: 

Java中为什么start方法不能重复调用而run方法可以?

 从 start 源码实现的第一行,我们就可以得到问题的答案,因为 start 方法在执行时,会先判断当前线程的状态是不是等于 0,也就是是否为新建状态 NEW,如果不等于新建状态,那么就会抛出“IllegalThreadStateException”非法线程状态异常,这就是线程的 start 方法不能被重复调用的原因。 它的执行过程是:当线程调用了第一个 start 方法之后,线程的状态就会从新建状态 NEW,变为就绪状态 RUNNABLE,此时再次调用 start 方法,JVM 就会判断出当前的线程已经不等于新建状态,从而抛出 IllegalThreadStateException 非法线程状态异常。

来源:https://juejin.cn/post/7064755729051156488

标签:Java,start,run,方法
0
投稿

猜你喜欢

  • C#中IEnumerable、ICollection、IList、List之间的区别

    2022-07-27 18:15:07
  • springBoot项目中使用@Value取值出现的问题及解决

    2023-05-29 12:59:16
  • ios百度地图的使用(普通定位、反地理编码)

    2023-07-03 15:26:17
  • C#实现中英文混合字符串截取的方法

    2022-07-11 10:02:35
  • phonegap教程使用jspdf库在应用中生成pdf文件(pdf生成方法)

    2022-10-29 05:50:11
  • 在maven工程里运行java main方法

    2023-09-18 04:33:20
  • 三步轻松搭建springMVC框架

    2023-02-01 05:38:34
  • 关于Spring Cloud 本地属性覆盖的问题

    2021-09-17 09:26:42
  • C#对DataTable中的某列进行分组

    2021-12-10 23:06:45
  • Java Zookeeper分布式分片算法超详细讲解流程

    2023-07-08 06:56:36
  • 一篇文章带你入门Springboot沙箱环境支付宝支付(附源码)

    2021-06-26 23:21:16
  • 详解Android Lint的原理及其使用

    2022-12-23 16:05:47
  • Java线程池高频面试题总结

    2023-10-22 02:12:34
  • c#简单读取文本的实例方法

    2022-02-16 14:51:52
  • Java中输出字符的ASCII值实例

    2023-02-27 08:59:11
  • springboot+chatgpt+chatUI Pro开发智能聊天工具的实践

    2023-10-30 05:38:03
  • Java实现排球比赛计分系统

    2021-07-11 09:11:14
  • Java8如何使用Lambda表达式简化代码详解

    2023-02-20 04:44:58
  • Android SharedPreferences实现记住密码和自动登录界面

    2023-06-15 20:07:00
  • Android SearchView搜索框组件的使用方法

    2023-06-25 08:13:42
  • asp之家 软件编程 m.aspxhome.com