妹子问我为啥启动线程时使用 Start 而不是 Run

网络 通信技术
今天团队里面的妹子问阿粉,为什么在启动线程的时候,都使用 start 方法,而不是 run 方法呢?

[[357639]]

 本文转载自微信公众号「Java极客技术」,作者鸭血粉丝。转载本文请联系Java极客技术公众号。   

今天团队里面的妹子问阿粉,为什么在启动线程的时候,都使用 start 方法,而不是 run 方法呢

还好阿粉平时一直有在学习,要不真的被妹子问住了

在多线程中,如果想让一个线程启动,你使用的方法一定是 thread.start() 方法,而不是 thread.run() 方法(啥,你用的不是 thread.start() 方法?乖,你的打开方式不对哦,下次不要这样了

有没有疑惑,为什么每次我们都习惯调用 start() 方法,为什么不直接调用 run() 方法来启动线程呢?

而且如果去看源码的话,你会发现,在 thread.start() 方法中,其实最后还是调用了 thread.run() 方法来执行

  1. Causes this thread to begin execution; the Java Virtual Machine 
  2.  calls the <code>run</code> method of this thread. 

上面的注释翻译一下:当线程开始执行时, JVM 会调用此线程的 run 方法

也就是说,线程的 run 方法是由 JVM 直接调用的,在 Java 中如果我们想要直接调用 run 方法也是可以的,因为在 Java 中 run 方法是 public 的

  1. @Override 
  2.    public void run() { 
  3.        if (target != null) { 
  4.            target.run(); 
  5.        } 
  6.    } 

那既然 start 方法最后调用的也是 run 方法,再加上 run 方法本身支持直接调用,那为啥我们平时写的程序都是调用 start 方法,而不是 run 方法呢

那是因为,如果直接调用 run 方法,就不是多线程了

为了方便解释,咱们看个小 demo :

  1. public class RunThread { 
  2.     public static void main(String[] args) { 
  3.         Thread runThread = new Thread(new Runnable() { 
  4.             @Override 
  5.             public void run() { 
  6.                 System.out.printf("Run begin another , 当前线程 : %s.%n" ,Thread.currentThread().getName()); 
  7.             } 
  8.         }); 
  9.  
  10.         // 启动线程 
  11.         runThread.start(); 
  12.  
  13.         // 直接调用 run 方法 -- 演示使用,实际中不要这么做! 
  14.         runThread.run(); 
  15.  
  16.         System.out.printf("Run begin , 当前线程 : %s.%n" ,Thread.currentThread().getName()); 
  17.     } 

上面的程序运行结果如下:

你会发现, runThread 的 run 方法被执行了两次

一次是 run 方法运行在自己的线程中,从 Run begin another , 当前线程 : Thread-0 可以看到,这个线程是运行在 Thread-0 中

另外一次是因为我们的程序代码直接调用了 run 方法,此时的线程运行在 main 线程中,从 Run begin another , 当前线程 : main 可以看出来

也就是说,如果我们直接调用 run 方法的话,线程并不是运行在自己的线程中,而是运行在了当前线程中

我们为什么要创建多线程?不就是希望多个线程并行执行,比如现在我是线程 A ,此时又起了一个线程,那么我希望这个线程是和线程 A 一起运行的,如果直接调用了 run 方法的话,就运行在线程 A 里面来了

并没有达到创建多线程的目标,这怎么行呢,对不对

所以在启动线程时,都是使用 start 方法,而不是 run 方法

这一点,其实在源码中也有说明:

the Java Virtual Machine calls the run method of this thread.

The result is that two threads are running concurrently:

the current thread (which returns from the call to the start method)

and the other thread (which executes its run method).

在 JVM 调用线程的 run 方法之后,结果就是两个线程同时运行:

  • 当前线程(从调用返回到 start 方法)
  • 另一个线程(执行 run 方法)

一个线程能不能 start 两次?

妹子搞懂了为什么线程一般都使用 start 方法,不使用 run 方法,因为调用的话,就违背了我们想要用多线程去处理的初衷

妹子又问阿粉,那一个线程是不是可以 start 两次呢?

负责任的阿粉赶紧告诉小妹妹是不可以的

如果一个线程启动两次,想都不用想会抛出 IllegalThreadStateException 这个异常

这个错误我们也能在源码中看到:

  1. if (threadStatus != 0) 
  2.     throw new IllegalThreadStateException(); 

线程开始 start 时,会首先判断 threadStatus 的值是否为 0 ,如果值不是 0 的话,说明这个线程的 state 状态不是 new 就抛出 IllegalThreadStateException 异常

啊?竟然还想问阿粉,线程的状态除了 new 还有什么?阿粉以前写过一篇,要不要看看:面试官没想到,一个 Java 线程生命周期,我可以扯半小时

 

责任编辑:武晓燕 来源: Java极客技术
相关推荐

2020-05-12 08:56:16

Java 线程开发

2024-08-01 10:10:24

MySQL场景搜索

2022-09-05 15:36:47

线程方法Java

2022-02-15 07:03:04

start 源码run线程

2023-03-29 09:01:46

HSBRGB模型

2013-03-25 10:14:18

NginxApache

2020-10-26 07:07:50

线程安全框架

2019-08-28 12:31:31

戴尔

2020-11-26 10:58:08

线程启动

2020-07-24 09:20:44

MapObject前端

2020-09-15 09:23:19

C++WindowsC#

2021-02-26 05:30:25

元素For-Each代码

2023-03-01 10:42:58

gRPC服务端设置

2021-03-26 11:50:28

Linuxexals

2021-06-30 12:47:12

标签HTML分辨率

2023-06-14 16:40:31

LinuxWSL

2022-05-02 17:34:25

大数据数据分析

2022-12-02 14:00:55

CIO交付能力

2024-02-20 20:12:09

C语言字符串Redis

2022-05-09 19:59:15

RedisLRU 算法
点赞
收藏

51CTO技术栈公众号