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

【Java】线程相关面试题 (基础)

文章目录

  • 线程与进程区别
  • 并行与并发区别解析
      • 概念含义
      • 资源利用
      • 执行方式
      • 应用场景
  • 创建线程
  • 线程状态
  • 如何保证新建的三个线程按顺序执行
  • wait方法和sleep方法的不同
      • 所属类和使用场景
      • 方法签名和参数说明
      • 调用`wait`方法的前提条件
      • 被唤醒的方式
      • 与`notify`/`notifyAll`方法的协作
      • 使用示例
      • 注意事项
  • 停止线程的三种方式

线程与进程区别

在这里插入图片描述

  • 进程的定义与实例
    • 进程是当程序被运行,从磁盘加载程序代码到内存时开启的。例如打开谷歌浏览器或txt文档等程序就是开启了一个进程,在Windows中有多实例进程(可打开多份,如浏览器、txt文档)和单实例进程(如tears客户端、企业微信在系统层面只能打开一份)。
  • 线程的定义与作用
    • 线程包含指令,交给CPU运行。进程至少包含一到多个线程,每个线程执行不同任务。
  • 线程与进程的区别
    • 进程是正在运行的程序实例,包含多个线程执行不同任务。不同进程使用不同内存空间,而当前进程下的所有线程可以共享该进程的内存空间。线程更轻量,其上下文切换成本一般比进程上下文切换成本低。面试时主要回答这三点:进程和线程的关系、内存占用情况(强调进程下线程共享内存)、线程更轻量且切换成本低。

并行与并发区别解析

概念含义

  • 并行:同一时间动手做多件事情的能力。例如在多核CPU下,多个核心可以同时执行不同的线程,像四核CPU能同时执行四个线程,这些线程是真正意义上的同时进行
  • 并发:同一时间应对多件事情的能力。在单核CPU中,由于只有一个核心,多个线程不能同时执行,而是通过任务管理器分配时间片,轮流使用CPU,虽然每个时间片只有一个线程执行,但因CPU切换速度快,宏观上给人一种并行的感觉,微观上实际是串行执行。例如家庭主妇独自做饭、打扫卫生、给孩子喂奶,一个人轮流交替做这些事,就如同单核CPU处理多线程任务。

资源利用

  • 并行:需要多核CPU等硬件资源支持,每个核心可以独立运行一个线程,实现真正的同时处理多个任务,充分利用了多核CPU的计算能力,提高了整体任务处理效率。
  • 并发:主要依赖于操作系统的调度机制,在单核CPU环境下,通过合理分配时间片给不同线程,让多个任务看起来像是同时在处理,有效利用了单个CPU的时间资源,避免某个线程长时间占用CPU导致其他线程等待过久,但整体效率受限于单核CPU的处理能力。

执行方式

  • 并行:多个任务在多个处理器或多核CPU的不同核心上同时执行,任务之间相互独立,不存在资源竞争(除非访问共享资源时需要进行同步处理),执行顺序是真正意义上的同时进行。
  • 并发:多个任务在单核CPU上通过时间片轮转的方式交替执行,每个任务执行一段时间后暂停,切换到下一个任务,由于时间片很短,给用户造成任务在同时进行的错觉,但实际上在微观层面是串行执行的,任务之间可能存在频繁的上下文切换开销。

应用场景

  • 并行:适用于计算密集型任务,如大规模数据处理、复杂科学计算等,通过将任务分解到多个核心上同时计算,可以显著缩短计算时间,提高计算性能。例如在图像渲染、视频编码解码等领域,利用多核CPU并行处理不同部分的图像或视频数据,能快速完成处理工作。
  • 并发:常用于I/O密集型任务,如网络通信、文件读写等操作,这些任务在等待I/O操作完成时会阻塞线程,使用并发可以在等待一个任务的I/O操作时切换到其他任务执行,提高CPU利用率,避免线程长时间空闲等待。比如在一个Web服务器中,同时处理多个客户端的请求,每个请求在等待数据库查询或文件读取等I/O操作时,服务器可以切换去处理其他客户端请求,提高整体响应能力。

创建线程

  1. 创建线程的方式介绍

    • 创建线程共有四种方式,分别是继承Thread类、实现Runnable接口、实现Callable接口和使用线程池创建线程。
  2. 继承Thread类创建线程

    • 定义一个类继承Thread类,重写run方法,在run方法中编写线程要执行的代码。
    • 使用时先创建该类的对象,然后调用start方法开启线程,new两次对象相当于开两个线程。
  3. 实现Runnable接口创建线程

    • 定义一个类实现Runnable接口,重写run方法,该方法为线程执行的代码。
    • 使用时先创建类的对象,将其包装在Thread类中,再调用Thread对象的start方法开启线程,new两次对象相当于开两个线程。
  4. 实现Callable接口创建线程

    • 定义一个类实现Callable接口,重写call方法,call方法有返回值(通过泛型指定)且可抛异常,call方法的代码为线程要执行的逻辑。
    • 使用时先创建类的对象,配合FutureTask包装该对象,再将FutureTask包装在Thread类中,调用Thread对象的start方法开启线程,通过FutureTask的get方法获取线程执行后的返回值。
  5. 使用线程池创建线程

    • 创建一个类实现Runnable或Callable接口,编写线程执行逻辑。
    • 使用时先创建固定大小的线程池(线程池后期会详细讲解),通过线程池的submit方法提交任务(即实现接口的类的对象),线程池会自动执行线程中的逻辑。
  6. Runnable和Callable的区别

    • 返回值:Runnable接口的run方法无返回值,Callable接口的call方法有返回值且需配合FutureTask使用get方法获取返回值。
    • 异常处理:run方法不能抛异常,只能内部try - catch处理;call方法可以抛异常。
  7. start方法和run方法的区别

    • 功能:start方法用于启动线程,线程独立执行run方法中的代码;run方法是普通方法,直接调用如同调用普通方法,在当前线程顺序执行代码。
    • 调用次数:start方法只能被调用一次启动线程,多次调用会抛异常;run方法可多次调用。
  8. 总结

    • 创建线程有继承Thread类、实现Runnable接口、实现Callable接口和使用线程池四种方式,项目中一般使用线程池创建线程。
    • Runnable和Callable的区别主要在返回值、异常处理方面。
    • start方法用于启动线程且只能调用一次,run方法是普通方法可多次调用。

线程状态

  1. 线程状态面试题介绍
    • 状态定义:参考Thread类的内部枚举类State,定义了六个线程状态,即new(新建)、runnable(可运行)、block(阻塞)、waiting(等待)、time waiting(时间等待)、terminated(终结)。

在这里插入图片描述

  1. 线程状态及转换初步讲解
    • 新建状态:创建线程对象时进入,如创建线程t1和t2时。
    • 就绪与运行状态:调用线程方法后进入就绪状态,抢到CPU时间片才有执行权,线程运行完成后进入死亡状态。
    • 阻塞状态:线程加锁时,未获得锁的线程进入阻塞状态,获得到锁后转为可运行状态。
    • 等待状态:线程内部调用wait方法进入等待状态,其他线程调用notify或notifyAll方法唤醒后变为可运行状态。
    • 时间等待状态:线程调用sleep方法进入时间等待状态,时间结束后转为可运行状态。
  2. 总结线程状态及转换
    • 线程状态总结:包含六个状态,新建、可运行、阻塞、等待、计时等待、终止状态。
    • 状态转换关系梳理
      • 新建到可执行:创建线程对象为新建状态,调用方法后转换为可执行状态。
      • 可执行到终止:线程获取CPU执行权并执行结束后为终止状态。
      • 可执行状态的其他转换
        • 可执行到阻塞:未获取到锁(如synchronized或Lock锁)进入阻塞状态,获得到锁的执行权后切换为可执行状态。
        • 可执行到等待:调用wait方法进入等待状态,其他线程调用notify或notifyAll唤醒后切换为可执行状态。
        • 可执行到计时等待:调用sleep方法进入计时等待状态,时间到后切换为可执行状态。

文章目录

  • 线程与进程区别
  • 并行与并发区别解析
      • 概念含义
      • 资源利用
      • 执行方式
      • 应用场景
  • 创建线程
  • 线程状态
  • 如何保证新建的三个线程按顺序执行
  • wait方法和sleep方法的不同
      • 所属类和使用场景
      • 方法签名和参数说明
      • 调用`wait`方法的前提条件
      • 被唤醒的方式
      • 与`notify`/`notifyAll`方法的协作
      • 使用示例
      • 注意事项
  • 停止线程的三种方式


如何保证新建的三个线程按顺序执行

  • 方法介绍
    • 对于“如何保证新建t1、t2、t3三个线程按顺序执行”这一面试题,可使用线程中的“join方法”来解决。该方法的作用是等待线程运行结束,调用此方法的线程会被阻塞,进入time waiting(时间等待)状态,直到被调用“join方法”的线程执行完成后,调用者才能继续执行。
  • 代码演示
  • 在代码中创建了t1、t2、t3三个线程,在t2线程中调用了t1的“join方法”,这意味着t2线程想要运行必须等待t1线程结束;在t3线程中调用了t2的“join方法”,所以t3线程需等待t2线程运行结束后才能运行。启动线程的顺序不影响最终结果,最终会按t1、t2、t3的顺序执行。通过代码执行结果展示了t1先执行,完成后t2执行,t2执行完t3执行,从而验证了这种方法可保证线程按顺序执行。
  1. notify和notifyAll的区别

    为notify是只随机唤醒一个等待(wait)方法的线程,而notifyAll是唤醒所有等待方法的线程。


wait方法和sleep方法的不同

在这里插入图片描述

在Java中,wait方法用于使当前线程等待,直到其他线程调用该对象的notify方法或notifyAll方法唤醒它,或者等待一定的时间(如果指定了超时时间)。以下是关于wait方法的详细介绍:

所属类和使用场景

  1. 所属类wait方法属于Object类,这意味着Java中的任何对象都可以调用该方法。
  2. 使用场景:主要用于多线程编程中,实现线程之间的协作和同步。例如,当一个线程需要等待某个条件满足时,可以调用wait方法进入等待状态,直到其他线程改变了共享资源的状态并通知它。

方法签名和参数说明

  1. 方法签名public final void wait() throws InterruptedExceptionpublic final native void wait(long timeout) throws InterruptedException
  2. 参数说明
    • 无参的wait方法会使当前线程无限期等待,直到被唤醒。
    • 带参数的wait方法接受一个long类型的参数,表示等待的超时时间(以毫秒为单位)。如果在指定时间内没有被唤醒,线程会自动苏醒并继续执行。

调用wait方法的前提条件

  1. 当前线程必须拥有该对象的锁。也就是说,wait方法必须在同步代码块(synchronized块)中调用,否则会抛出IllegalMonitorStateException异常。
  2. 例如,以下代码演示了正确调用wait方法的方式:
synchronized (object) {// 当前线程获取了object对象的锁,可以调用wait方法object.wait();
}

被唤醒的方式

  1. 其他线程调用notify方法:唤醒在此对象监视器上等待的单个线程。如果有多个线程在等待,选择是任意的,由操作系统的调度策略决定。
  2. 其他线程调用notifyAll方法:唤醒在此对象监视器上等待的所有线程。被唤醒的线程将竞争重新获取对象的锁,然后继续执行。
  3. 等待超时:如果调用了带超时参数的wait方法,当超时时间到达时,线程会自动苏醒,继续执行后续代码。

notify/notifyAll方法的协作

  1. wait方法与notify/notifyAll方法必须在同一对象上调用,以实现线程之间的正确协作。
  2. 通常,一个线程在等待某个条件时调用wait方法,而另一个线程在改变条件后调用notifynotifyAll方法来唤醒等待的线程。

使用示例

以下是一个简单的示例,展示了wait方法和notify方法的基本用法:

public class WaitNotifyExample {public static void main(String[] args) {final Object lock = new Object();// 线程1:等待条件满足Thread thread1 = new Thread(() -> {synchronized (lock) {try {System.out.println("线程1:开始等待");lock.wait(); // 释放锁并等待System.out.println("线程1:被唤醒,继续执行");} catch (InterruptedException e) {e.printStackTrace();}}});// 线程2:改变条件并通知线程1Thread thread2 = new Thread(() -> {synchronized (lock) {System.out.println("线程2:改变条件,并通知线程1");lock.notify(); // 唤醒等待的线程1}});thread1.start();try {Thread.sleep(1000); // 确保线程1先进入等待状态} catch (InterruptedException e) {e.printStackTrace();}thread2.start();}
}

在上述示例中,线程1获取lock对象的锁后调用wait方法进入等待状态,同时释放锁。线程2获取lock对象的锁后调用notify方法唤醒线程1,线程1被唤醒后重新竞争锁,获取锁后继续执行后续代码。

注意事项

  1. 在使用wait方法时,必须在循环中调用,以避免虚假唤醒(spurious wakeup)的问题。虚假唤醒是指线程在没有被其他线程明确唤醒的情况下苏醒,可能是由于操作系统或JVM的内部原因。例如:
while (condition) {synchronized (object) {object.wait();}
}
  1. 调用wait方法的线程会释放对象的锁,但在被唤醒后重新竞争锁。如果多个线程同时竞争锁,唤醒顺序是不确定的,取决于操作系统的调度策略。
  2. wait方法会抛出InterruptedException异常,当线程在等待过程中被中断时,会抛出该异常。因此,在调用wait方法时,需要正确处理异常,以确保程序的稳定性和正确性。

在这里插入图片描述


文章目录

  • 线程与进程区别
  • 并行与并发区别解析
      • 概念含义
      • 资源利用
      • 执行方式
      • 应用场景
  • 创建线程
  • 线程状态
  • 如何保证新建的三个线程按顺序执行
  • wait方法和sleep方法的不同
      • 所属类和使用场景
      • 方法签名和参数说明
      • 调用`wait`方法的前提条件
      • 被唤醒的方式
      • 与`notify`/`notifyAll`方法的协作
      • 使用示例
      • 注意事项
  • 停止线程的三种方式


停止线程的三种方式

  1. 停止线程的三种方式
    • 使用退出标志:通过定义一个标志变量(如flag),在run方法中使用循环条件控制线程执行,当标志变量改变时,线程正常退出。例如,在my interrupt 1类中,run方法里使用while循环(while (!flag)),线程在循环内打印信息并睡眠3秒。主线程启动该线程后睡眠6秒,然后将flag改为true,使线程在6秒后正常退出。
    • 调用stop方法(不推荐)stop方法可以强行终止线程,但此方法已作废不推荐使用。
    • 调用interrupt方法:该方法包含两种情况。
      • 一是打断阻塞的线程(如处于sleepwaitjoin状态的线程),调用interrupt会抛出InterruptException异常;
      • 二是打断正常的线程,可根据线程的打断状态标记是否退出线程,与第一种使用退出标志的方式类似。
      • 在这里插入图片描述

相关文章:

【Java】线程相关面试题 (基础)

文章目录 线程与进程区别并行与并发区别解析概念含义资源利用执行方式应用场景 创建线程线程状态如何保证新建的三个线程按顺序执行wait方法和sleep方法的不同所属类和使用场景方法签名和参数说明调用wait方法的前提条件被唤醒的方式与notify/notifyAll方法的协作使用示例注意事…...

【数字化】华为一体四面细化架构蓝图

导读:华为的“一体四面”企业架构设计方法是一种综合性的管理框架,它通过业务架构、信息架构、应用架构和技术架构的集成设计,构建出一个既符合业务需求,又具备高度灵活性和可扩展性的IT系统。这种架构设计方法强调从业务视角出发…...

frameworks 之 WMS添加窗口流程

frameworks 之 触摸事件窗口查找 1.获取WindowManager对象2.客户端添加view3. 服务端添加view (NO_SURFACE)4.重新布局 (DRAW_PENDING)4.1 创建 SurfaceControl 5.通知绘制 (COMMIT_DRAW_PENDING, READY_TO_SHOW, HAS_DRAWN)5. 1 布局测量和刷新 6.总结 …...

搜索方法归类全解析

搜索方法归类全解析 搜索方法是人工智能和计算机科学中用于解决问题、优化路径或发现数据模式的关键技术。根据不同的标准,搜索方法可以被分为多种类别。本文将详细介绍这些分类标准,并探讨每一类的特点及其代表算法,同时补充更多关于搜索的相…...

第1关:简易考试系统之用户注册

任务描述 本关任务:实现简易考试系统中新用户注册的功能。 编程要求 仔细阅读右侧编辑区内给出的代码框架及注释,在 Begin-End 中实现简易考试系统中新用户注册的功能,具体要求如下: User.java 提供了用户的基本信息&#xff0c…...

VMware的三种网络模式——在NAT模式下开放接口为局域网内其他主机提供服务

众所周知 VMware 有三种常用的网络通讯模式,分别是:Bridged(桥接模式)、NAT(网络地址转换模式)、Host-Only(仅主机模式),它们各有不同的用法。 Bridged 桥接模式是与主机…...

智慧地下采矿:可视化引领未来矿业管理

图扑智慧地下采矿可视化平台通过整合多源数据,提供实时 3D 矿井地图及分析,提升了矿产开采的安全性与效率,为矿业管理提供数据驱动的智能决策支持,推动行业数字化转型。...

流量主微信小程序工具类去水印

工具类微信小程序流量主带后台管理,可开通广告,带自有后台管理,不借助第三方接口 介绍 支持抖音,小红书,哔哩哔哩视频水印去除,功能实现不借助第三方平台。可实现微信小程序流量主广告变现功能&#xff0c…...

代码随想录算法【Day5】

DAY5 1.熟悉哈希表的数据结构:数组、map和set,使用方法、使用场景 2.哈希表应用场景:解决给你一个元素,判断它在集合里是否出现过。 242.有效的字母异位词 本题用数组解决的。 class Solution { public:bool isAnagram(strin…...

Leetcode 3403. Find the Lexicographically Largest String From the Box I

Leetcode 3403. Find the Lexicographically Largest String From the Box I 1. 解题思路2. 代码实现 题目链接:3403. Find the Lexicographically Largest String From the Box I 1. 解题思路 这一题我一开始的思路是想用动态规划,结果发现想复杂了&…...

【游戏设计原理】36 - 环境叙事

一、 分析并总结 核心要点 环境叙事的本质:将游戏的设定视为叙事的一部分,利用环境元素(如物品、对话、视觉效果等)传递故事和信息。世界设定的重要性:一个强大的世界设定可以像角色一样,驱动叙事并增强玩…...

Python 中的 lambda 函数和嵌套函数

Python 中的 lambda 函数和嵌套函数 Python 中的 lambda 函数和嵌套函数Python 中的 lambda 函数嵌套函数(内部函数)封装辅助函数闭包和工厂函数 Python 中的 lambda 函数和嵌套函数 Python 中的 lambda 函数 Lambda 函数是基于单行表达式的匿名函数。…...

语言模型评价指标

1. BLEU(Bilingual Evaluation Understudy) 目标:衡量生成文本和参考文本之间的词汇相似性。 计算步骤: N-gram 匹配: 将生成文本和参考文本分解成 1-gram、2-gram、…、N-gram(通常取到 4-gram&#xff…...

工程师 - MSYS2介绍

https://www.msys2.org/ MSYS2 是一系列工具和库,为您提供了一个易于使用的环境,用于构建、安装和运行本地 Windows 软件。 MSYS2 is a collection of tools and libraries providing you with an easy-to-use environment for building, installing an…...

算法基础三:插入排序

定义 插入排序(英语:Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用…...

小米汽车加速出海,官网建设引领海外市场布局!

面对国内市场的饱和态势,中国企业出海步伐纷纷加速,小米也是其中的一员。Canalys数据显示,2024年第三季度,小米以13.8%的市场份额占比,实现了连续17个季度位居全球前三的成绩。 据“36 氪汽车”报道,小米汽…...

Python Polars快速入门指南:LazyFrames

前文已经介绍了Polars的Dataframe, Contexts 和 Expressions,本文继续介绍Polars的惰性API。惰性API是该库最强大的功能之一,使用惰性API可以设定一系列操作,而无需立即运行它们。相反,这些操作被保存为计算图,只在必要…...

什么是网络安全(Cybersecurity)?

不同组织机构对网络安全(Cybersecurity或Cyber Security)的定义不尽相同。从目标上来说,网络安全主要用于保护网络、计算机、移动设备、应用程序及数据等资产免受网络攻击,避免造成数据泄露、业务中断等安全问题。 网络钓鱼、勒索…...

VBA批量插入图片到PPT,一页一图

Sub InsertPicturesIntoSlides()Dim pptApp As ObjectDim pptPres As ObjectDim pptSlide As ObjectDim strFolderPath As StringDim strFileName As StringDim i As Integer 设置图片文件夹路径strFolderPath "C:\您的图片文件夹路径\" 请替换为您的图片文件夹路径…...

Pandas-DataFrame入门

文章目录 一. Pandas DataFrame简介二. 加载数据集1. 目的2. 步骤① 导包② 加载csv③ 查看数据类型及属性④ Pandas与Python常用数据类型对照 三. 查看部分数据1. 根据列名加载部分列数据① 加载一列数据,通过df[列名]方式获取② 加载多列数据,通过df[[…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...

AI,如何重构理解、匹配与决策?

AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...

CSS | transition 和 transform的用处和区别

省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

【JVM】Java虚拟机(二)——垃圾回收

目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四&#xff…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...