当前位置: 首页 > news >正文

冲刺大厂 | 一个线程调用两次start()方法会出现什么现象?

大家好,我是冰河~~

今天给大家分享的面试题是:一个线程调用两次start()方法会出现什么现象?这道面试题是一道关于多线程的基础面试题,很多小伙伴对这个面试题不太了解,其实,如果你看过JDK中关于Thread类的源码,那这道面试题对你来说就能过轻松应对了。今天,我们就一起来聊聊这道面试题,以及面试官问这道题的面试分析拓展知识。

优质回答

Java 的线程是不允许启动两次的,第二次调用必然会抛出 IllegalThreadStateException,这是一种运行时异常,表示非法的线程状态异常。

关于线程生命周期的不同状态,在 Java 5 以后,线程状态被明确定义在其公共内部枚举类型 java.lang.Thread.State 中,分别是:

  • 新建(NEW),表示线程被创建出来还没真正启动的状态,可以认为它是个 Java 内部状态。
  • 就绪(RUNNABLE),表示该线程已经在 JVM 中执行,当然由于执行需要计算资源,它可能是正在运行,也可能还在等待系统分配给它 CPU 片段,在就绪队列里面排队。
  • 在其他一些分析中,会额外区分一种状态 RUNNING,但是从 Java API 的角度,并不能表示出来。
  • 阻塞(BLOCKED),这个状态和我们前面两讲介绍的同步非常相关,阻塞表示线程在等待 Monitor lock。比如,线程试图通过 synchronized 去获取某个锁,但是其他线程已经独占了,那么当前线程就会处于阻塞状态。
  • 等待(WAITING),表示正在等待其他线程采取某些操作。一个常见的场景是类似生产者消费者模式,发现任务条件尚未满足,就让当前消费者线程等待(wait),另外的生产者线程去准备任务数据,然后通过类似 notify 等动作,通知消费线程可以继续工作了。Thread.join() 也会令线程进入等待状态。
  • 计时等待(TIMED_WAIT),其进入条件和等待状态类似,但是调用的是存在超时条件的方法,比如 wait 或 join 等方法的指定超时版本,如下面示例:
  public final native void wait(long timeout) throws InterruptedException;
  • 终止(TERMINATED),不管是意外退出还是正常执行结束,线程已经完成使命,终止运行,也有人把这个状态叫作死亡。

在第二次调用 start() 方法的时候,线程可能处于终止或者其他(非 NEW)状态,但是不论如何,都是不可以再次启动的。

面试分析

今天的面试题看似简单,实则是对面试者基础知识的考察,很多大厂在面试时,很重视面试者对基础知识的掌握程度,往往这些基础知识是大家最容易忽视的。

知识拓展

线程的通用生命周期

线程在运行的过程中,会经历几种状态之间的转换,而线程在这几种状态之间的转换流程,基本上就构成了线程的生命周期。本小节,就简单介绍下线程的通用生命周期。

线程的通用生命周期总体上可以分为五种状态,分别为:初始状态、可运行状态、运行状态、休眠状态和终止状态

在这里插入图片描述

可以看出,线程的通用生命周期可以分为初始状态、可运行状态、运行状态、休眠状态和终止状态五种状态。

(1)初始状态:初始状态比较特殊,这种状态属于编程语言层面特有的状态,处于初始状态的线程只是线程在编程语言层面被创建了,但是在操作系统层面,并没有真正的创建线程。

(2)可运行状态:在操作系统层面,线程被真正的创建,并且可以分配CPU执行。

(3)运行状态:处于运行状态的线程已经获取到CPU资源,正在运行。

(4)休眠状态:线程正在等待某个事件的发生(例如等待I/O事件的完成),或者调用了一个阻塞的API正处于阻塞状态(例如以阻塞的方式读写文件等),此时的线程处于休眠状态。

(5)终止状态:线程正常运行结束或者出现异常,就会进入终止状态。

线程的通用生命周期中各状态之间的转换关系如下所示。

(1)初始状态转换成可运行状态:处于初始状态的线程,实际上并没有在操作系统中创建对应的线程,当在操作系统中创建了对应的线程时,此时线程就会从初始状态转换成可运行状态。

(2)可运行状态转换成运行状态:如果操作系统中存在空闲的CPU资源,则操作系统会将空闲的CPU资源分配给一个处于可运行状态的线程,处于可运行状态的线程获得CPU资源后就会转换成运行状态。也就是说,处于可运行状态的线程,被操作系统调度获取到CPU资源后,就会从可运行状态转换成运行状态。

(3)运行状态转换成可运行状态:当正在运行的线程CPU时间片用完时,就会从运行状态转换成可运行状态。

(4)运行状态转换成休眠状态:处于运行状态的线程如果等待某个事件的发生(例如,等待I/O事件的完成),或者调用了一个阻塞的API(例如,以阻塞的方式读写文件等),此时处于运行状态的线程就会释放CPU的资源,从运行状态转换成休眠状态。

(5)休眠状态转换成可运行状态:如果处于休眠状态的线程等待的事件已经发生(例如,等待的I/O事件已经完成),或者调用的阻塞API已经完成操作(例如,以阻塞的方式读写文件已经完成),则线程就会从休眠状态转换成可运行状态。

(6)运行状态转换成终止状态:处于运行状态的线程正常运行结束,或者出现异常,就会从运行状态转换成终止状态。处于终止状态的线程,不会再转换成其他的状态,线程的生命周期也就结束了。

注意:在线程的通用生命周期中,只有处于运行状态的线程可以直接转换成终止状态和休眠状态,处于其他状态的线程都不能直接转换成终止状态和休眠状态。处于休眠状态的线程只能直接转换成可运行状态,不能直接转换成其他状态。

Java中线程的生命周期

在Java中,线程的生命周期主要包括:初始化状态、可运行状态、阻塞状态、等待状态、超时等待状态和终止状态。其中,可运行状态又包括运行状态和就绪状态。

在这里插入图片描述

可以看出,在Java的线程生命周期中,总体上包含初始化状态、可运行状态、等待状态、超时等待状态、阻塞状态和终止状态六种状态。

(1)初始化状态:线程在Java中被创建,但是还没有调用线程对象的start()方法,也就是说,还没有创建操作系统层面对应的线程。

(2)可运行状态:Java线程生命周期中的可运行状态,包含操作系统中线程的运行状态和就绪状态。

(3)等待状态:处于等待状态的线程需要等待其他线程对当前线程进行通知或者中断等操作,从而进入下一个线程状态。

(4)超时等待状态:处于超时等待状态的线程需要在指定的时间内,等待其他线程对当前线程进行通知或者中断等操作。如果在指定的时间内,存在其他线程对当前线程进行通知或者中断等操作,则当前线程进入下一个状态。否则超过指定的时间,当前线程也会进入下一个状态。

(5)阻塞状态:处于阻塞状态的线程需要等待其他线程释放锁,或者等待进入synchronized临界区。

(6)终止状态:表示当前线程执行完毕,包括正常执行结束和异常退出。

Java的线程生命周期中的可运行状态,涵盖了运行状态和就绪状态。

(1)运行状态:对应操作系统中的运行状态。

(2)就绪状态:对应操作系统中的就绪状态。

在Java的线程生命周期中,各状态之间的转换关系如下所示。

1.初始化状态转换成可运行状态的场景

在Java层面,调用线程对象的start()方法,会在操作系统层面创建对应的线程,此时,线程的状态就会从初始化状态转换成可运行状态。

2.可运行状态与等待状态互相转换的场景一

(1)线程a调用synchronized(obj)获取到对象锁后,调用obj.wait()方法时,线程a的状态会从可运行状态转换成等待状态。

(2)在满足(1)时,此时线程b调用synchronized(obj)获取到对象锁后,调用obj.notify()方法、obj.notifyAll()方法、a.interrupt()方法,此时会有两种情况,如下所示。

l 线程a竞争锁成功,则线程a会由等待状态转换成可运行状态。

l 线程a竞争锁失败,则线程a会由等待状态转换成阻塞状态。

3.可运行状态与等待状态互相转换的场景二

(1)线程a调用线程b的join()方法时,线程a会由可运行状态转换成等待状态。

(2)在满足(1)时,线程b运行结束,或者调用了线程a的interrupt()方法,则线程a会从等待状态转换成可运行状态。

4.可运行状态与等待状态互相转换的场景三

(1)线程a调用LockSupport.park()方法时,线程a会从可运行状态转换成等待状态。

(2)在满足(1)时,其他线程调用LockSupport.unpark(a),或者调用线程a的interrupt()方法,线程a会从等待状态转换成可运行状态。

5.可运行状态与超时等待状态互相转换的场景一

(1)线程a调用synchronized(obj)获取到对象锁后,调用obj.wait(long n)方法,则线程a会从可运行状态转换成超时等待状态。

(2)在满足(1)时,线程a的等待时间超过了n毫秒,或者线程b调用synchronized(obj)获取到对象锁后,调用obj.notify()方法、obj.notifyAll()方法、a.interrupt()方法,此时会有两种情况,如下所示。

l 线程a竞争锁成功,则线程a会由超时等待状态转换成可运行状态。

l 线程a竞争锁失败,则线程a会由超时等待状态转换成阻塞状态。

6.可运行状态与超时等待状态互相转换的场景二

(1)线程a调用Thread.sleep(long n)方法,则线程a会从可运行状态转换成超时等待状态。

(2)在满足(1)时,线程a的等待时间超过n毫秒,则线程a会从超时等待状态转换成可运行状态。

7.可运行状态与超时等待状态互相转换的场景三

(1)线程a调用了线程b的join(long n)方法时,线程a会从可运行状态转换成超时等待状态。

(2)在满足(1)时,线程a的等待时间超过n毫秒,或者线程b运行结束,或者调用了线程a的interrupt()方法,线程a会从超时等待状态转换成可运行状态。

8.可运行状态与超时等待状态互相转换的场景四

(1)线程a调用Locksupport.parkNanos(long nacos)方法,或者调用LockSupport.parkUntil(long millis)方法时,线程a会从可运行状态转换成超时等待状态。

(2)在满足(1)时,其他线程调用LockSupport.unpark(a),或者调用线程a的interrupt()方法,或者线程a等待超时,则线程a会从超时等待状态转换成可运行状态。

9.可运行状态与阻塞状态互相转换的场景一

(1)线程a与线程b共同争抢同一个悲观锁,线程b争抢成功,则线程a会从可运行状态转换成阻塞状态。

(2)在满足(1)时,线程b释放锁时,线程a获取到锁,则线程a会从阻塞状态转换成可运行状态。

10.可运行状态与阻塞状态互相转换的场景二

(1)线程a调用synchronized(obj)获取对象锁时,竞争失败,则线程a会从可运行状态转换成阻塞状态。

(2)在满足(1)时,调用synchronized(obj)获取对象锁时竞争成功的线程,执行同步代码块完毕,就会唤醒所有阻塞在obj对象上的线程,这些被唤醒的线程会重新竞争,如果线程a竞争成功,则线程a会从阻塞状态转换成可运行状态。如果线程a竞争失败,则线程a继续保持阻塞状态。

11.可运行状态转换成终止状态的场景

线程a正常执行结束,或者由于某种原因异常退出,线程a就会从可运行状态转换成终止状态。

如果一个线程转换成终止状态,那么就标注着这个线程已经运行结束,不能再次转换成其他状态。

好了,今天就到这儿吧,我是冰河,我们下期见~~

相关文章:

冲刺大厂 | 一个线程调用两次start()方法会出现什么现象?

大家好,我是冰河~~ 今天给大家分享的面试题是:一个线程调用两次start()方法会出现什么现象?这道面试题是一道关于多线程的基础面试题,很多小伙伴对这个面试题不太了解,其实,如果你看过JDK中关于Thread类的…...

leaflet(一)初始化地图

Leaflet 与天地图结合使用,可以通过天地图提供的 API 获取地图瓦片,并在 Leaflet 地图上显示。 1. 安装依赖 首先,确保你已经安装了 Leaflet 和 Vue: npm install leaflet npm install vue-leaflet npm install leaflet.tilela…...

Unity开发Hololens项目

Unity打包Hololens设备 目录Visual Studio2019 / Visual Studio2022 远端部署设置Visual Studio2019 / Visual Studio2022 USB部署设置Hololens设备如何查找自身IPHololens设备门户Unity工程内的打包设置 目录 记录下自己做MR相关:Unity和HoloLens设备的历程。 Vi…...

立志最细,FreeRtos的中断管理(Interrupt Management)函数,详解!!!

前言:本文参考,韦东山老师开发文档,连接放在最后。 为什么需要中断管理函数? 在FreeRtos操作系统中,需要实时响应性,也就是随时随地必须保证正常多任务的运行,如果有中断发生,因为中…...

作业2-线性回归的Matlab代码实现

一、前言 相关配置:Matlab 2020a(版本的影响应该不大,.m代码基本都能运行,个人感觉就是Simulink对版本的要求高一些) 二、任务描述 基于近两节课的理论推导,用代码实现线性回归,并对预测结果进…...

用jQuery在canvas上绘制绝对定位的元素

在Web开发中,我们经常需要在canvas上精确定位和绘制元素。虽然canvas本身不支持DOM元素的定位,但我们可以借助jQuery来实现这一功能。本文将介绍如何使用jQuery在canvas上实现元素的绝对定位。 1. 基本思路 我们的基本思路是: 创建一个包含canvas的容器div将需要定位的元素放…...

Android中 tools:text 和 android:text区别

首先引入命名空间 <androidx.constraintlayout.widget.ConstraintLayoutxmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"/androidx.constraintlayout.widget.ConstraintLayout> tools:te…...

Wordpress GutenKit 插件 远程文件写入致RCE漏洞复现(CVE-2024-9234)

0x01 产品简介 GutenKit 是一个WordPress的页面构建器,在 Gutenberg 设计您的下一个 WordPress 网站。借助 Gutenberg 的原生拖放界面、50+ WordPress 块、14+ 多功能模块和 500+ 模板,您可以在几分钟内创建专业、响应迅速的 Web 内容。 0x02 漏洞概述 Wordpress GutenKit…...

Redis历史漏洞未授权RCE复现

Redis是一个开源的内存数据库&#xff0c;它用于存储数据&#xff0c;并提供高性能、可扩展性和丰富的数据结构支持。 Redis复现文章 Redisssrf漏洞利用探测内网 RedisInsight/RedisDesktopManager可视化连接工具 漏洞原理 &#xff08;1&#xff09;redis绑定在 0.0.0.0:…...

Greenhills学习总结

学习背景&#xff1a;近期参与xx项目过程中&#xff0c;遇到较多的关于代码集成编译的知识盲区&#xff0c;因此需要进行相关知识的学习和扫盲。 参考资料&#xff1a;GreenHills2017.7编译手册:本手册是GreenHills 2017.7.14版编译器的软件使用手册。该手册详细介绍了GreenHi…...

【深入学习Redis丨第八篇】详解Redis数据持久化机制

前言 Redis支持两种数据持久化方式&#xff1a;RDB方式和AOF方式。前者会根据配置的规则定时将内存中的数据持久化到硬盘上&#xff0c;后者则是在每次执行写命令之后将命令记录下来。两种持久化方式可以单独使用&#xff0c;但是通常会将两者结合使用。 一、持久化 1.1、什么…...

【27续】c++项目练习

定义一个或多个类&#xff0c;来描述以下需求&#xff1a; 汽车&#xff0c;有多个轮胎&#xff0c;一个发动机&#xff0c;品牌&#xff0c;型号, 价格&#xff0c; 行驶里程。 轮胎&#xff0c;有品牌&#xff0c;尺寸&#xff0c;气压。 发动机&#xff0c;有品牌&#x…...

Lazarus Query转EXCEL功能

Lazarus Query转EXCEL功能 需要用到控件XMLXSDExporter1 procedure SaveToExcel(AQuery:TSQLQuery); var SaveDialog: TSaveDialog; Ext:String; begin SaveDialog : TSaveDialog.Create(nil); SaveDialog.Filter:Excel 97-2003文件(*.xls)|*.XLS; if SaveDialog.Exec…...

AnaTraf | 深入探讨DNS流量分析:保障网络稳定性的关键

目录 什么是DNS流量分析&#xff1f; DNS流量的组成 为什么进行DNS流量分析&#xff1f; DNS流量分析在IT运维中的应用 1. 故障排查 2. 性能监控与优化 3. 安全检测 AnaTraf 网络性能监控系统NPM | 全流量回溯分析 | 网络故障排除工具 在当今数字化时代&#xff0c;互联…...

P1017 [NOIP2000 提高组] 进制转换

题目是意思就是转化 负进制 题干给定内容确实看不懂 我是看了别人的题解才会的 注意点&#xff1a;进制中不能出现负数&#xff08;解决方法 向前借一位 这是核心代码&#xff09;抓住 被除数除数*商余数 if(tp<0){//模是负数 就要转化为正数tp-y;xy;}//自己在纸上模拟一…...

计算机网络—vlan(虚拟局域网)

内容补充 冲突域 如果两台设备同时发送数据&#xff0c;他们的数据会互相干扰&#xff0c;那么他们就处于同一冲突域&#xff0c;例如集线器&#xff08;总线型&#xff0c;所有设备共享带宽&#xff09;的所有端口都处于冲突域。 广播域 如果一台设备发送数据&#xff0c;…...

C++头文件大全及解释

在C编程中&#xff0c;头文件起到了非常重要的作用。它们包含了函数声明、类定义和其他预处理指令&#xff0c;为程序提供了所需的各种功能和库。本文将介绍一些常见的C头文件&#xff0c;并提供具体实例来说明它们的用途和解释。 1. <iostream> 这是C标准库中最常用的头…...

基于 Django 的电商比价系统

想在毕业设计中展示自己的开发能力吗&#xff1f;今天给大家推荐一个绝对能让你脱颖而出的项目——基于 Django 框架的电商比价系统&#xff01;主打实用创新&#xff0c;你一定能用它拿下好成绩&#xff5e;&#x1f929; ✨项目核心功能亮点&#xff1a; 完善的用户系统&…...

Excel重新踩坑2:Excel数据类型;自定义格式(设置显示格式);分列操作;其他常用操作;一些重要操作

0、Excel数据类型&#xff1a;文本、数字、逻辑值、错误值 文本数据类型&#xff1a;输入什么显示什么&#xff1b;常见错误值 VALUE&#xff1a;文本与数字运算&#xff1b; DIV/0&#xff1a;分母为0&#xff1b; NAME&#xff1a;公式名称错误&#xff1b; N/A&#xff1a;…...

python从0快速上手(十四)数据库操作

Python学习&#xff1a;数据库操作篇 在这个信息爆炸的时代&#xff0c;数据库就像是一个个巨大的宝藏库&#xff0c;里面藏着无数珍贵的数据宝石。而Python&#xff0c;就是那把能够打开这些宝藏库的神奇钥匙。在这一章中&#xff0c;我们将一起学习如何使用Python来操作数据…...

【热门主题】000004 案例 Vue.js组件开发

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【热…...

Ingress-nginx中HTTPS的强制转发

文章目录 在使用aws 的NLB转发流量到ingress时&#xff0c;发现NLP上生成的转发配置不符合正常预期&#xff0c;如下图&#xff1a; ingress-nginx service 配置如下&#xff1a; apiVersion: v1 kind: Service metadata:annotations:service.beta.kubernetes.io/aws-load-b…...

C++深入探寻二叉搜索树:数据管理的智慧之选

✨✨小新课堂开课了&#xff0c;欢迎欢迎~✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C&#xff1a;由浅入深篇 小新的主页&#xff1a;编程版小新-CSDN博客 前言&#xff1a; 我们在前面已经学习过有关…...

Python 文件 I/O 入门指南

Python 文件 I/O 入门指南 文章目录 Python 文件 I/O 入门指南一、文件的打开与关闭二、文件的读取三、文件的写入四、文件的定位五、文件的属性六、处理不同类型的文件七、错误处理八、总结 在 Python 编程中&#xff0c;文件输入输出&#xff08;I/O&#xff09;是一项非常重…...

Atlas800昇腾服务器(型号:3000)—YOLO全系列NPU推理【检测】(五)

服务器配置如下&#xff1a; CPU/NPU&#xff1a;鲲鹏 CPU&#xff08;ARM64&#xff09;A300I pro推理卡 系统&#xff1a;Kylin V10 SP1【下载链接】【安装链接】 驱动与固件版本版本&#xff1a; Ascend-hdk-310p-npu-driver_23.0.1_linux-aarch64.run【下载链接】 Ascend-…...

1.2.3 TCP IP模型

TCP/IP模型&#xff08;接网叔用&#xff09; 网络接口层 网络层 传输层 应用层 理念&#xff1a;如果某些应用需要“数据格式转换”“会话管理功能”&#xff0c;就交给应用层的特定协议去实现 tip&#xff1a;数据 局部正确不等于全局正确 但是&#xff0c;数据的 全局正…...

选择、冒泡和插入排序及其优化版本课件

视频链接&#xff1a;是趣味编程的个人空间-是趣味编程个人主页-哔哩哔哩视频...

Matlab自学笔记三十九:日期时间型数据的算术运算:加减运算

1.说明 时间点和&#xff08;日历&#xff09;持续时间是可加的&#xff0c;结果是时间点&#xff1b;两个时间点是可减的&#xff0c;结果是持续时间&#xff0c;用时分秒表示&#xff1b;时间型和浮点数运算&#xff0c;结果是时间型&#xff0c;浮点数默认单位是天&#xf…...

Java-多线程2

什么是线程&#xff1f; 线程是 cpu调度和执行的单位。 多个线程共享进程的堆和方法区资源&#xff0c;但每个线程有自己的程序计数器、虚拟机栈和本地方法栈。 如何实现线程 继承Thread类 实现步骤&#xff1a; 创建自定义类&#xff0c;继承Thread类 重写run方法 创建自定…...

POWER_CONMETRICS的packet wakeup events触发条件的代码走读

摘要&#xff1a; adb shell dumpsys connmetrics 的packet wakeup events触发条件&#xff1a;首先App是无法控制packet wakeup events的事件日志打印&#xff0c;主要App联网过程中网络状态或配置发生变化时由系统netd自动触发的统计。 通俗理解&#xff1a;目前主要表示触…...