Java面试必问!run() 和 start() 方法到底有啥区别?

简介: 在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。



大家好!我是小米,今天我们来聊一个经常出现在 Java 面试中的经典面试题:线程的 run() 和 start() 有什么区别?为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法?

这个问题看似简单,其实背后涉及到多线程的运行机制、线程生命周期的管理,甚至是 Java 内部的底层实现。现在,就让我们通过一个故事来一起揭秘这个问题,帮助你在面试中更自信地应对这一难题!

一场关于线程的小故事

假设你正在准备一个大型的在线直播系统,在高并发场景下,你需要确保每个用户的直播流都能够并行处理。为了解决这个问题,你决定在程序中使用 Java 的多线程机制来实现。

你写了一个简单的线程类,代码如下:

这段代码看起来很简单,它实现了 Thread 类并重写了 run() 方法。你可能会想到,调用 run() 方法就可以启动线程并执行直播流处理了。

但是,当你运行下面的代码时,事情变得有点不对劲:

问题来了:你发现程序不会启动新线程,而只是同步执行了 run() 方法里的内容!这究竟是为什么呢?难道 run() 方法有问题吗?我们明明是继承了 Thread 类,重写了 run() 方法,难道这就是启动线程的方式吗?

run() 方法和 start() 方法的区别

在 Java 中,线程的启动不是直接调用 run() 方法就能完成的。实际上,run() 方法是线程的入口点,它包含了线程执行的代码,但它并不会直接启动新的线程。

1、run() 方法

run() 方法只是一个普通的方法,它的作用是描述线程应该执行的任务。如果你直接调用 run() 方法,那么它就像是一个普通的函数调用,在当前线程中执行,而并没有创建新线程。

也就是说,调用 run() 方法时,代码不会在新的线程中执行,而是会在当前线程中顺序执行。所以,在我们上面的代码中,thread.run() 其实就是直接调用了 run() 方法,而没有启动新的线程。

2、start() 方法

而 start() 方法才是启动新线程的正确方式。当我们调用 start() 方法时,它会做两件事:

  • 启动一个新的线程。
  • 在新的线程中调用我们在 run() 方法中写的代码。

总结:start() 方法实际上是一个底层的操作,它会告诉 JVM 创建一个新的线程,并调用 run() 方法。而 run() 方法仅仅是线程执行的入口,它不会自动启动新线程。简单来说,start() 负责启动线程,run() 负责执行线程任务

为什么我们不能直接调用 run() 方法?

那么,问题就来了:既然 run() 方法是线程任务的实现,为什么我们不能直接调用 run() 方法来启动线程呢?这似乎让人摸不着头脑。

原因就在于: 直接调用 run() 方法并不会创建新的线程,它只是将 run() 方法的代码当作普通的方法调用来执行。在这种情况下,线程任务仍然是在当前线程中同步执行的,而不是在新线程中并行执行。

我们回到之前的代码,如果我们像这样调用 run():

这时,run() 方法的代码依然是在主线程中执行的,而不是在新的线程中执行。程序并没有并行地执行线程任务,实际上它只是将线程任务当做普通的任务来执行了。因此,我们看到的输出就是:

它是在主线程中执行的,而不是在新的线程中并行执行的。

start() 方法底层的实现

那我们再来深入探讨一下,start() 方法背后到底做了些什么?如果你深入到 Java 的源代码中,你会发现,start() 方法是调用了 Thread 类中的 start0() 方法,这个方法会在底层启动一个新的操作系统线程,并在新线程中调用 run() 方法。

简单来说:

  • start() 方法:启动一个新的线程,并在该线程中执行 run() 方法。
  • run() 方法:线程的执行内容,是线程开始执行后运行的代码。

线程的生命周期

为了更好地理解 start() 和 run() 的区别,我们还需要了解线程的生命周期。在 Java 中,线程的生命周期一般分为以下几个状态:

  • 新建(New):线程刚被创建,还没有启动。
  • 就绪(Runnable):线程已经启动,但可能还没有开始执行,等待 CPU 分配时间。
  • 运行中(Running):线程获得 CPU 时间片并正在执行任务。
  • 阻塞(Blocked):线程被阻塞,等待某个资源或事件的发生。
  • 终止(Terminated):线程执行完毕,生命周期结束。

start() 方法在底层实际上会让线程进入 就绪 状态,从而使得线程能够进入 运行中 状态并执行 run() 方法。

小结:为什么要使用 start()?

我们回到最初的问题:为什么我们需要使用 start() 方法来启动线程,而不能直接调用 run() 方法?

  • run() 方法是线程的任务代码,它并不会创建新的线程,而是当前线程直接执行。
  • start() 方法负责启动新线程,并且在新线程中调用 run() 方法。

所以,如果我们想要在新的线程中并行执行任务,就必须调用 start() 方法来启动线程,而不能直接调用 run() 方法。直接调用 run() 方法就相当于将线程任务当作普通的函数来执行,根本不会并行运行。

小贴士:多线程编程的常见错误

在实际开发中,我们经常会遇到一些常见的多线程错误,了解并避免这些问题非常重要。

  • 误用 run() 方法:很多初学者误以为调用 run() 方法就能启动线程,其实这只会在当前线程中执行 run() 方法。正确的方式是调用 start()。
  • 线程安全问题:在多线程环境中,多个线程同时操作共享资源时,容易发生线程安全问题。需要使用 synchronized 或者其他线程安全的工具类来避免竞态条件。
  • 忘记线程同步:在一些场景下,多线程共享资源时,如果没有正确同步,可能会导致不可预测的结果。

END

今天我们通过一个简单的故事,深入了解了 Java 中 run() 和 start() 方法的区别,解答了为什么我们调用 start() 方法时会执行 run() 方法,以及为什么不能直接调用 run() 方法来启动线程。掌握这些基本概念,对我们在面试中的表现和日常的多线程开发都大有裨益。

希望这篇文章对你有所帮助,如果你喜欢这样的内容,记得点赞和分享哦!下次我们继续聊更多有趣的 Java 面试题!

公众号对技术型文章的推送机制有所调整,需要大家多多点赞在看转发收藏,才能让更多技术同行们能看到优质的技术分享~

我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号软件求生,获取更多技术干货!

相关文章
|
14天前
|
供应链 监控 安全
对话|企业如何构建更完善的容器供应链安全防护体系
阿里云与企业共筑容器供应链安全
171330 12
|
16天前
|
供应链 监控 安全
对话|企业如何构建更完善的容器供应链安全防护体系
随着云计算和DevOps的兴起,容器技术和自动化在软件开发中扮演着愈发重要的角色,但也带来了新的安全挑战。阿里云针对这些挑战,组织了一场关于云上安全的深度访谈,邀请了内部专家穆寰、匡大虎和黄竹刚,深入探讨了容器安全与软件供应链安全的关系,分析了当前的安全隐患及应对策略,并介绍了阿里云提供的安全解决方案,包括容器镜像服务ACR、容器服务ACK、网格服务ASM等,旨在帮助企业构建涵盖整个软件开发生命周期的安全防护体系。通过加强基础设施安全性、技术创新以及倡导协同安全理念,阿里云致力于与客户共同建设更加安全可靠的软件供应链环境。
150295 32
|
24天前
|
弹性计算 人工智能 安全
对话 | ECS如何构筑企业上云的第一道安全防线
随着中小企业加速上云,数据泄露、网络攻击等安全威胁日益严重。阿里云推出深度访谈栏目,汇聚产品技术专家,探讨云上安全问题及应对策略。首期节目聚焦ECS安全性,提出三道防线:数据安全、网络安全和身份认证与权限管理,确保用户在云端的数据主权和业务稳定。此外,阿里云还推出了“ECS 99套餐”,以高性价比提供全面的安全保障,帮助中小企业安全上云。
201961 14
对话 | ECS如何构筑企业上云的第一道安全防线
|
2天前
|
机器学习/深度学习 自然语言处理 PyTorch
深入剖析Transformer架构中的多头注意力机制
多头注意力机制(Multi-Head Attention)是Transformer模型中的核心组件,通过并行运行多个独立的注意力机制,捕捉输入序列中不同子空间的语义关联。每个“头”独立处理Query、Key和Value矩阵,经过缩放点积注意力运算后,所有头的输出被拼接并通过线性层融合,最终生成更全面的表示。多头注意力不仅增强了模型对复杂依赖关系的理解,还在自然语言处理任务如机器翻译和阅读理解中表现出色。通过多头自注意力机制,模型在同一序列内部进行多角度的注意力计算,进一步提升了表达能力和泛化性能。
|
6天前
|
存储 人工智能 安全
对话|无影如何助力企业构建办公安全防护体系
阿里云无影助力企业构建办公安全防护体系
1251 8
|
7天前
|
人工智能 自然语言处理 程序员
通义灵码2.0全新升级,AI程序员全面开放使用
通义灵码2.0来了,成为全球首个同时上线JetBrains和VSCode的AI 程序员产品!立即下载更新最新插件使用。
1291 24
|
9天前
|
机器学习/深度学习 自然语言处理 搜索推荐
自注意力机制全解析:从原理到计算细节,一文尽览!
自注意力机制(Self-Attention)最早可追溯至20世纪70年代的神经网络研究,但直到2017年Google Brain团队提出Transformer架构后才广泛应用于深度学习。它通过计算序列内部元素间的相关性,捕捉复杂依赖关系,并支持并行化训练,显著提升了处理长文本和序列数据的能力。相比传统的RNN、LSTM和GRU,自注意力机制在自然语言处理(NLP)、计算机视觉、语音识别及推荐系统等领域展现出卓越性能。其核心步骤包括生成查询(Q)、键(K)和值(V)向量,计算缩放点积注意力得分,应用Softmax归一化,以及加权求和生成输出。自注意力机制提高了模型的表达能力,带来了更精准的服务。
|
7天前
|
消息中间件 人工智能 运维
1月更文特别场——寻找用云高手,分享云&AI实践
我们寻找你,用云高手,欢迎分享你的真知灼见!
566 22
1月更文特别场——寻找用云高手,分享云&AI实践
|
6天前
|
机器学习/深度学习 人工智能 自然语言处理
|
12天前
|
人工智能 自然语言处理 API
阿里云百炼xWaytoAGI共学课DAY1 - 必须了解的企业级AI应用开发知识点
本课程旨在介绍阿里云百炼大模型平台的核心功能和应用场景,帮助开发者和技术小白快速上手,体验AI的强大能力,并探索企业级AI应用开发的可能性。