关于后端:为什么start方法不能重复调用而run方法却可以

47次阅读

共计 2568 个字符,预计需要花费 7 分钟才能阅读完成。

初学线程时,总是将 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();}

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

从上述后果能够看出,二者调用之后的执行成果都是一样,都能够胜利执行工作。然而,如果在执行线程的时候,加上打印以后线程的名称就能看出二者的不同了,如下代码所示:

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();}

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

从上述后果咱们能够看出:当调用 run 办法时,其实是调用以后主程序 main 来执行办法体的;而调用 start 办法才是真正的创立一个新线程来执行工作

区别 1

run 办法和 start 办法的第一个区别是:调用 start 办法是真正开启一个线程来执行工作,而调用 run 办法相当于执行一般办法 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();

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

从上述后果能够看出,run 办法屡次调用可用失常执行,而第二次调用 start 办法时程序就报错了,提醒“IllegalThreadStateException”非法线程状态异样。

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

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

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

总结

run 办法和 start 办法的次要区别如下:

  1. 办法性质不同:run 是一个一般办法,而 start 是开启新线程的办法。
  2. 执行速度不同:调用 run 办法会立刻执行工作,调用 start 办法是将线程的状态改为就绪状态,不会立刻执行。
  3. 调用次数不同:run 办法能够被反复调用,而 start 办法只能被调用一次。

start 办法之所以不能被反复调用的起因是,线程的状态是不可逆的,Thread 在 start 的实现源码中做了判断,如果线程不是新建状态 NEW,则会抛出非法线程状态异样 IllegalThreadStateException。

是非审之于己,毁誉听之于人,得失安之于数。

公众号:Java 面试真题解析

面试合集:https://gitee.com/mydb/interview

正文完
 0