为什么启动线程不直接调用run(),而要调用start(),如果调用两次start()方法会有什么后果

简介: 1位工作6年的小伙伴去某里P6一面,被问到这样一道面试题,说,为什么启动一个线程不直接调用run()方法,而要调用start()方法来启动,如果调用两次start()会有什么后果?

1位工作6年的小伙伴去某里P6一面,被问到这样一道面试题,说,为什么启动一个线程不直接调用run()方法,而要调用start()方法来启动,如果调用两次start()会有什么后果?

1、run()和start()的区别

首先回答为什么启动线程不能直接调用run()方法,而要调用start()方法,我从以下4个方面来回答:

fe7dcdbcf3438d8c6501d4a949a87083.jpg

第1:start()方法是Java线程约定的内置方法,能够确保代码在新的线程上下文中运行。


第2:start()方法包含了触创建新线程的特殊代码逻辑。run()方法是我们自己写的代码,很显然没有这个能力。


第3:如果直接调用run()方法,那么它只是一个普通的方法调用,程序中依然只有一个主线程,并且只能顺序执行,需要等待run()方法执行结束后才能继续执行后面的代码。


第4:我们创建线程的目的是为了更充分地利用CPU资源,如果直接调用run()方法,就失去了创建线程的意义了。

2、调用两次start()的后果

了解了run()方法和start()方法的区别,那如果调用两次start()方法会有什么后果呢?在Java中,线程的start()方法只能被调用一次,如果第二次调用会抛出 IllegalThreadStateException,这是一种运行时异常,多次调用 start 被认为是编程错误。

44ff0f41767df7bb2173fcc914dd3097.jpg

在Java中,线程的运行状态被定义成了5个枚举值,分别是:


1、新建(NEW),线程已经创建好了,但是还没有调用start()方法启动。


2、就绪(RUNNABLE),这个状态下的线程可能正在运行,也可能还在就绪队列里面,等待系统分配CPU资源。


在操作系统中,会额外区分一种状态叫做RUNNING,但是从 Java API 的角度,并不能表示出来。关于这个问题,我在前面的视频中,有讲过关于《线程状态流转原理》有兴趣的小伙伴可以去我的主页找到。


3、阻塞(BLOCKED),表示线程处于等待Monitor Lock的状态。


4、等待(WAITING),表示线程处于条件等待状态,当触发条件后会唤醒。比如wait/notify等。


5、计时等待(TIMED_WAIT),它和WAITING状态是一样的,只是多了一个超时条件触发机制。


6、终止(TERMINATED),表示线程执行结束。


在Java API 中,影响线程运行状态的因素,如图所示:

02bc6fdce7c476b4e6a2141df0c6a2e6.jpg

在我们第一次调用 start() 方法的时候,线程可能处于终止或者其他非 NEW的状态,再次调用start()方法的时候,相当于让这个正在运行的线程重新运行一遍。不管是从线程安全的角度来看,还是从线程本身的执行逻辑来看,它都是不合理的。


因此,为了避免这个问题出现,Java会先去判断当前线程的运行状态。


好了,以上就是我对Java线程的start()方法和run()方法的理解。


我是被编程耽误的文艺Tom,关注我,面试不再难!

b47a6e98314749488df58a0cfbc33b50.gif

相关文章
|
19天前
|
监控 测试技术 程序员
解决线程死循环问题的有效方法
作为开发者想必都清楚,多线程应用程序的开发为我们日常开发工作中提供了并发执行任务的能力,但线程死循环问题却是一个常见而令人头疼的挑战,因为线程死循环可能导致系统的不稳定性、资源浪费以及应用程序的异常运行,所以准确地定位和妥善处理线程死循环现象,并在编码阶段就避免潜在风险,成为开发人员必须面对的重要问题,线程死循环问题的解决不仅有助于提高系统的稳定性和可用性,还能优化资源利用和提升应用程序的性能,通过采取适当的预防和处理措施,开发人员能够避免线程陷入无尽的循环,并及时发现和解决潜在问题。那么本文就来分享一下关于如何处理线程死循环问题,以及如何在编码阶段规避潜在风险。
29 2
解决线程死循环问题的有效方法
|
2月前
|
Java 调度 C#
C#学习系列相关之多线程(一)----常用多线程方法总结
C#学习系列相关之多线程(一)----常用多线程方法总结
|
2月前
|
Java 测试技术
血的教训--如何正确使用线程池submit和execute方法
血的教训--如何正确使用线程池submit和execute方法
27 1
|
3月前
|
人工智能 Java API
Python 潮流周刊#28:两种线程池、四种优化程序的方法
Python 潮流周刊#28:两种线程池、四种优化程序的方法
24 1
|
4月前
|
监控 Java 应用服务中间件
剑指JUC原理-3.线程常用方法及状态(下)
剑指JUC原理-3.线程常用方法及状态
59 0
|
4月前
|
安全 Java Kotlin
面试必备:Kotlin 线程同步的 N 种方法
面试必备:Kotlin 线程同步的 N 种方法
84 0
|
5月前
|
Java
学习多线程之yield方法
学习多线程之yield方法
45 0
|
3天前
|
安全 Java
【JAVA】线程的run()和start()有什么区别?
【JAVA】线程的run()和start()有什么区别?
|
9天前
|
NoSQL
线程死循环的定位方法
线程死循环的定位方法
17 2
|
11天前
使用代理IP池实现多线程的方法
使用代理IP池实现多线程的方法