JAVA:多线程常见的面试题和答案

请关注微信公众号:拾荒的小海螺
博客地址:http://lsk-ww.cn/

1、并发编程三要素?

  • 原 子 性
    原子性指的是一个或者多个操作,要么全部执行并且在执行的过程中不被其他操作打断,要么就全部都不执行。
  • 可 见 性
    可见性指多个线程操作一个共享变量时,其中一个线程对变量进行修改后,其他线程可以立即看到修改的结果。
  • 有 序 性
    有序性,即程序的执行顺序按照代码的先后顺序来执行。

1、Java中的volatile关键字有什么作用?

答:volatile关键字在Java中主要用于变量的同步,其核心作用可以概括为两点:

  • 保证内存可见性: 当一个变量定义为volatile之后,它会保证对所有线程的可见性。这意味着当一个线程修改了一个volatile变量的值,新值对于其他线程来说是立即可见的。
  • 禁止指令重排序: volatile还可以防止指令重排序优化。在没有volatile修饰的多线程程序中,为了提高性能,编译器和处理器可能会对指令进行重排序,但是一旦变量被volatile修饰,就会禁止这种重排序,以确保程序的执行顺序与代码的顺序相同。

虽然volatile可以保证单次读/写的原子性,但它无法保证整个操作的原子性。例如,volatile变量的i++操作无法保证原子性。

2、创建线程的方式有哪些?

  • 通过继承 Thread 类创建线程类
  • 实现 Runnable 接口创建线程类
  • 通过 Callable 和 Future 接口创建线

3、Java 如何保证线程安全?

  • 使用同步代码块
  • 使用同步方法
  • 使用 Lock 锁机制, 通过创建 Lock 对象,采用 lock()加锁,unlock()解锁,来保护指
    定的代码块。

4、描述 Synchronized、ReentrantLock 的区别 ?

  • synchronized 是关键字,ReentrantLock 是 API 接口
  • Lock 需要手动加锁,手动释放锁
  • synchronized 不可中断,ReentrantLock 可中断、可超时
  • synchronized 是非公平锁,ReentrantLock 公平、非公平皆可
  • ReentrantLock 支持 Condition,多条

5、在Java中wait和sleep方法的不同?

答:通常会在电话面试中经常被问到的Java线程面试问题。最大的不同是在等待时wait会释放锁,而sleep一直持有锁。Wait通常被用于线程间交互,sleep通常被用于暂停执行。

6、为什么我们调用 start()方法时会执行 run()方法,为什么我们不能直接调用 run()方法?

答:当你调用 start()方法时你将创建新的线程,并且执行在 run()方法里的代码 。但是如果你直接调用 run()方法,它不会创建新的线程也不会执行调用线程的代码 ,只会把 run 方法当作普通方法去执行。

7、Java 中用到的线程调度算法是什么?

答:计算机通常只有一个 CPU,在任意时刻只 能执行一条机器指令,每个线程只有获得CPU 的使用权才能 执行指令 .所谓多线程的并发运行,其实是指从宏观上看,各个线程轮流获得 CPU 的使用权,分别执行 各自的任务.在运行池中,会有多个处于就绪状态的线程在等待 CPU,JAVA 虚拟机的 一项任务就是负责线程 的调度 ,线程调度是指按照特定机制为多个线程分配 CPU 的使用权.。

有两种调度模型:分时调度模型和抢占式调度模型。

分时调度模型是指让所有的线程轮流获得 cpu 的使 用权,并且平均分配每个线程占用的 CPU 的时间片这个也比较好理解。

java 虚拟机采用抢占式调度模型,是指优先让可运行池中优先级高的线程占用CPU,如果可运行池中 的线程优 先级相同,那么就随机 选择一个线程,使其占用CPU。处于运行状态的 线程会一 直运行,直至它不得不 放弃 CPU。

8、什么是 Daemon 线程?它有什么意义?

答:所谓后台(daemon)线程,是指在程序运行的时候在后台提供一种通用服务的线程,并且这个线程并不属于程序中不可或缺的部分。因此,当所有的非后台线程结束时,程序也就终止了,同时会杀死进程中的所有后台线程。反过来说,只要有任何非后台线程还在运行,程序就不会终止。必须在线程启动之前调用setDaemon()方法,才能把它设置为后台线程。

注意:后台进程在不执行 finally子句的情况下就会终止其 run()方法。

比如:JVM 的垃圾回收线程就是 Daemon 线程 ,Finalizer 也是守护线程。

9、CyclicBarrier 和 CountDownLatch 的区别

  • CountDownLatch 简单的说就是一个线程等待,直到他所等待的其他线程都执行完成并且调用 countDown()方法发出通知后,当前线程才可以继续执行。

  • cyclicBarrier 是所有线程都进行等待,直到所有线程都准备好进入 await()方法之后,所有线程同时开始执行!

  • CountDownLatch 的计数器只能 使用一次。而 CyclicBarrier 的计数器可以使用 reset() 方法重置。所以 CyclicBarrier 能处理更为复杂的业务场景,比如如果计算发生错误,可以重置计数器,并让线程们重新执行一次。

  • CyclicBarrier 还提供其他有用的方法,比如 getNumberWaiting 方法可以获得 CyclicBarrier 阻塞的线程数量。isBroken 方法用来知道阻塞的线程是否被中断 。如果被中断返回 true,否则返回 false。

10、什么是 CAS 与其 常见的问题?

答:CAS是一种基于锁的操作,而且是乐观锁。在 java 中锁分为乐观锁和悲观锁。悲观锁是将资源锁住,等一个之前获得锁的线程释放锁之后,下一个线程才可以访问。而乐观锁采取了一种宽泛的态度,通过某种方式不加锁来处理资源,比如通过给记录加 version 来获取数据,性能较悲观锁有很大的提高。

CAS常见的问题:

  • CAS 容 易 造 成 ABA 问 题
    一个线程 a 将数值改成了 b,接着又改成了 a,此时 CAS 认为是没有变化,其实是已经变化过了,而这个问题的解决方案可以使用版本号标识,每操作一次version 加 1。在 java5 中,已经提供了 AtomicStampedReference 来解决问题。
  • 不 能 保 证 代 码 块 的 原 子 性
    CAS 机制所保证的知识一个变量的原子性操作 ,而不能保证整个代码块的原子性。比如需要保证 3 个变量共同进行原子性的更新,就不得不使用 synchronized 了。
  • CAS 造 成 CPU 利 用 率增 加
    之前说过了 CAS 里面是一个循环判断的过程,如果线程一直没有获取到状态,cpu资源会一直被占用

11、线程池的优点?

  • 重用存在的线程,减少对象创建销毁的开销。
  • 可有效的控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
  • 提供定时执行、定期执行、单线程、并发数控制 等功能。

12、常用的并发工具类有哪些?

  • CountDownLatch
  • CyclicBarrier
  • Semaphore
  • Exchanger

13、Java 线程具有五中基本状态

  • 新 建 状 态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();
  • 就 绪 状 态 ( Runnable) :当 调用线程对象的 start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待 CPU 调度执行,并不是说执行了 t.start()此线程立即就会执行;
  • 运 行 状 态 ( Running):当 CPU 开始调度处于就绪状态的线程时,此时线程才得以真 正执行,即进入到 运行状态 。注:就 绪状 态是进入到运 行状态的 唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;
  • 阻 塞 状 态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对 CPU的使用权 ,停止执行 ,此时进入阻塞 状态,直到其进 入到就绪状态 ,才 有机 会再次被 CPU 调用以进入到运行状态。
  • 死 亡 状 态(Dead):线程执行完了或者因异常退出了 run()方法,该线程结束生命周期
    在这里插入图片描述

14、线程池的创建方式有哪些

  • newSingleThreadExecutor() 创建一个单线程化的线程池;
  • newFixedThreadPool() 创建固定线程数量的线程池;
  • newCachedThreadPool() 创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程。
  • newScheduledThreadPool() 创建一个可以延迟或定期执行任务的线程池;
  • newSingleThreadScheduledExecutor()创建一个单线程执行器,该执行器可以安排命令在给定延迟后运行,或定期执行;
  • newWorkStealingPool() 使用可用处理器数量作为其目标并行度级别创建工作窃取线程池 [ JDK1.8新增]。
  • 创建ThreadPoolExecutor对象来实现自定义线程池创建

FixedThreadPool 和 SingleThreadExecutor 传入的最后一个参数阻塞队列 ”workQueue“,默认的长度INTEGER.MAX_VALUE,而它们允许的最大线程数量又是有限的,所以当请求线程的任务过多线程不够用时,它们会在队列中等待,又因为队列的长度特别长,所以可能会堆积大量的请求,导致OOM。

CachedThreadPool 和 ScheduledThreadPool 它们的阻塞队列长度有限,但是传入的第二个参数maximumPoolSize 为Integer.MAX_VALUE,这就意味着当请求线程的任务过多线程不够而且队列也满了的时候,线程池就会创建新的线程,因为它允许的最大线程数量是相当大的,所以可能会创建大量线程,导致OOM。

15、synchronized 的作用?

答:在 Java 中,synchronized 关键字是用来控制线程同步的,就是在多线程的环境下,控制 synchronized 代码段不被多个线程同时执行。synchronized 既可以加在一段代码上,也可以加在方法上。

16、什么是 AQS

答:AQS 是 AbustactQueuedSynchronizer 的简称, 它是一个 Java 提高的底层同步工具类,用一个 int 类型的变量表示同步状态,并提供了一系列的 CAS 操作来管理这个同步状态。
AQS 是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的ReentrantLock,Semaphore,其他的诸如ReentrantReadWriteLock,SynchronousQueue,FutureTask 等等皆是基于AQS 的。

AQS 支持两种同步方式:

  • 独占式
  • 共享式

17、sleep 方法和 wait 方法有什么区别?

答:这个问题常问,sleep 方法和 wait 方法都可以用来放弃 CPU 一定的时间,不同点在于如果线程持有某个对象的监视器,sleep 方法 不会放弃这个对象的监 视器,wait 方法会放弃这个对象的监视器。

18、ThreadLocal 是什么?有什么用?

答:ThreadLocal 是一个本地线程副本变量工 具类。主要用于将私有线程和该 线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,特别适用于各个线程依赖不通的变量值完成操作的场景。简单说 ThreadLocal 就是一种以空间换 时间的做法,在每个 Thread 里面维护了一个以开地址法实现的 ThreadLocal.ThreadLocalMap,把数据进行隔离,数据不共享,自然就没有线程安全方面的问题了。

19、ConcurrentHashMap 的并发度是什么

答:ConcurrentHashMap 的并 发度 就是 segment 的大 小, 默认 为 16,这 意味 着最多同 时可 以有 16 条线 程操 作 ConcurrentHashMap,这 也是ConcurrentHashMap 对 Hashtable 的最 大优 势, 任何 情 况下 ,Hashtable 能同时有 两条 线程 获取 Hashtable 中的 数据 吗?

20、什么是多线程的上下文切换

答:多线程的上下文切换是指 CPU 控制权由 一个已经正在运行的线程切换到另外一个就绪并等待获取 CPU 执行权的线程的过程。

21、什么是线程调度器(Thread Scheduler)和时间分片(TimeSlicing)?

答:线程调度器是一个操作系统服务,它负责为 Runnable 状态的线程分配 CPU 时间。一旦我们创建一个线程并启动它,它的执行便依赖于线程调度器的实现。

时间分片是指将可用的 CPU 时间分配给可用的 Runnable 线程的过程。分配 CPU 时间可以基于线程优先级或者线程等待的时间。线程 调度并不受到 Java 虚拟机控制,所以由应用程序来控制它是更好的选择(也就是说不要让你的程序依赖于线程的优
先级)。

22、Java 线程数过多会造成什么异常?

  • 线 程 的 生 命 周 期 开 销 非 常 高
  • 消 耗 过 多 的 CPU 资源
    如果可运行的线程数量多于可用处理器的数量,那么有线程将会被闲置。大量空闲的线程会占用许多内存,给垃圾回收器带来压力,而且大量的线程在竞争 CPU资源时还将产生其他性能的开销。
  • 降 低 稳 定 性
    JVM 在可创建线程的数 量上存在一个限制 ,这个限制值将随着平台的不同而不同,并且承受着多个因素制约,包括 JVM 的启动参数、Thread 构造函数中请求栈的大小,以及底层操作系统对线程的限制等。如果破坏了这些限制,那么可能抛出OutOfMemoryError 异常。

23、线程池中核心线程数量大小怎么设置?

  • CPU密集型任务:
    比如像加解密,压缩、计算等一系列需要大量耗费 CPU 资源的任务,大部分场景下都是纯 CPU 计算。尽量使用较小的线程池,一般为CPU核心数+1。因为CPU密集型任务使得CPU使用率很高,若开过多的线程数,会造成CPU过度切换。
  • IO密集型任务:
    比如像 MySQL 数据库、文件的读写、网络通信等任务,这类任务不会特别消耗 CPU 资源,但是 IO 操作比较耗时,会占用比较多时间。可以使用稍大的线程池,一般为2*CPU核心数。IO密集型任务CPU使用率并不高,因此可以让CPU在等待IO的时候有其他线程去处理别的任务,充分利用CPU时间。

另外:线程的平均工作时间所占比例越高,就需要越少的线程;线程的平均等待时间所占比例越高,就需要越多的线程;
以上只是理论值,实际项目中建议在本地或者测试环境进行多次调优,找到相对理想的值大小。

24、说说submit(和 execute两个方法有什么区别?

答:submit() 和 execute() 都是用来执行线程池的,只不过使用 execute() 执行线程池不能有返回方法,而使用 submit() 可以使用 Future 接收线程池执行的返回值。

25、volatile如何保证可见性?

答:Volatile是通过MESI缓存一致性协议和总线嗅探机制来保证可见性的

  • 什么是MESI协议?
    MESI协议其实是一个变量在内存中的不同状态!MESI 是指4种状态的首字
M 修改 (Modified) 当一个线程要修改便令
E 独享、互斥 (Exclusive) 当一个线程拿到了共享变量,此时为独享状态!
S 共享 (Shared) 当多个线程都拿到了共享变量,此时为共享状态!
I 无效 (Invalid) 线程丢弃了自己工作内存中的变量,为无效状态!
  • MESI协议如何保证可见性?
    首先cpu会根据共享变量是否带有Volatile字段,来决定是否使用MESI协议保证缓存一致性。如果有Volatile,汇编层面会对变量加上Lock前缀,当一个线程修改变量的值后,会马上经过store、write等原子操作修改主内存的值(如果不加Lock前缀不会马上同步),为什么监听到修改会马上同步呢?就是为了触发cpu的嗅探机制,及时失效其他线程变量副本。
  • cpu总线嗅探机制
    cpu总线嗅探机制监听到这个变量被修改,就会把其他线程的变量副本由共享S置为无效I,当其他线程在使用变量副本时,发现其已经无效,就回去主内存中拿一个最新的值。
  • 在写入主内存时为什么要加锁?在哪里加锁?
    变量被修改后同步到主内存的过程中会在store之前加锁,写完后解锁,这个锁只有在修改的时候才会加,锁粒度非常小。因为在store时可能已经经过了总线,但此时还没有write进主内存,总线却触发了嗅探机制,其他线程的变量已失效,当其他线程去主内存读最新数据时,新数据还未write进来,产生脏数据!
  • Lock前缀的作用
    使CPU缓存数据立即写会主内存(Volatile修饰的变量会带lock前缀)触发总线嗅探机制和缓存一致性协议MESI来失效其他线程的变量
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/661803.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智能仓储物流系统(WMS)系列-货品与分类管理

好的应用系统应是细分简单,界面简洁易操作,程序代码简洁易懂的。

【傻呱呱】python安装phook3(Windows端)

前期准备 swig程序Visual Studio C 构建工具 配置swig程序 将下载好的“swig-4.2.1”压缩包解压到C盘从C盘打开“swig-4.2.1”文件夹并复制文件夹路径 在开始菜单里搜索“环境变量”,点击“编辑系统环境变量” 点击“环境变量” 找到“path”并双击 点击“新建” …

MFC工控项目实例一主菜单制作

1、本项目用在WIN10下安装的vc6.0兼容版实现。创建项目名为SEAL_PRESSURE的MFC对话框。在项目res文件下添加相关256色ico格式图片。 2、项目名称:密封压力试验机 主菜单名称: 系统参数 SYS_DATA 系统测试 SYS_TEST 选择型号 TYP_CHOICE 开始试验 TES_STA…

汽车电子学习【车载网络CAN/LIN】

车载网络CAN/LIN知识总结 STM32F1开发板测试 STM32测试程序 /** CAN 通信报文内容设置*/ void CAN_SetMsg(void) { #if CAN_STDTxMessage.StdId 0x12;TxMessage.IDE CAN_ID_STD; #elseTxMessage.ExtId 0x1314; //使用的扩展IDTxMessage.IDE CAN_ID_EXT; //扩展模式 #…

MySQL注入 — Dns 注入

DNS注入原理 通过子查询,将内容拼接到域名内,让load_file()去访问共享文件,访问的域名被记录此时变为显错注入,将盲注变显错注入,读取远程共享文件,通过拼接出函数做查询,拼接到域名中,访问时将访问服务器,…

AI大模型日报#0529:杨红霞创业入局“端侧模型”、Ilya左膀右臂被Claude团队挖走

导读:AI大模型日报,爬虫LLM自动生成,一文览尽每日AI大模型要点资讯!目前采用“文心一言”(ERNIE 4.0)、“零一万物”(Yi-34B)生成了今日要点以及每条资讯的摘要。欢迎阅读&#xff0…

计算机毕业设计 | SpringBoot+vue仓库管理系统(附源码)

1,绪论 1.1 项目背景 随着电子计算机技术和信息网络技术的发明和应用,使着人类社会从工业经济时代向知识经济时代发展。在这个知识经济时代里,仓库管理系统将会成为企业生产以及运作不可缺少的管理工具。这个仓库管理系统是由:一…

美团拼好饭小程序mtgsig1.2分析(补环境分析)

声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!wx a15018601872 本文章未…

AUS GLOBAL 荣获 Brokersview 颁奖盛典多项殊荣

2024年1月31日在迪拜 Sheikh Zayed Rd - Trade Centre - Trade Centre 1 举行的 Brokersview 颁奖盛典上,AUS GLOBAL(澳洲环球)再次展现了其在金融行业的卓越实力,并荣获多项殊荣。 AUS GLOBAL 作为一家全球领先的金融服务提供商…

【Linux进程篇】Linux进程管理——进程创建与终止

W...Y的主页 😊 代码仓库分享💕 目录 进程创建 fork函数初识 写时拷贝 fork常规用法 fork调用失败的原因 进程终止 进程退出场景 _exit函数 exit函数 return退出 进程创建 fork函数初识 在linux中fork函数时非常重要的函数,它从已…

【蓝桥杯嵌入式】 第六届国赛

目录 题目 配置 注意事项 代码 - 默写大师 EEPROM读写函数 LED驱动函数 ADC采集 上电初始化 LCD 按键 PWM互补输出 全部代码 hardware.c hardware.h control.c control.h main.c 题目 配置 注意事项 复制LCD的工程,先配置资源 --- 勾选完选项一…

Java基于saas模式云MES制造执行系统源码Spring Boot + Hibernate Validation什么是MES系统?

Java基于saas模式云MES制造执行系统源码Spring Boot Hibernate Validation 什么是MES系统? MES制造执行系统,通过互联网技术实现从订单下达到产品完成的整个生产过程进行优化管理。能有效地对生产现场的流程进行智能控制,防错防呆防漏&…

docker占用磁盘空间大小排查

首先进入到 /var/lib/docker/overlay2 目录下,查看谁占用的较多 cd /var/lib/docker/overlay2/du -s ./* | sort -rn | more再通过目录名查找容器名 docker ps -q | xargs docker inspect --format {{.State.Pid}}, {{.Id}}, {{.Name}}, {{.GraphDriver.Data.WorkDir}} | gre…

【4.vi编辑器使用(下)】

一、vi编辑器的光标移动 二、vi编辑器查找命令 1、命令::/string 查找字符串 n:继续查找 N:反向继续查找 /^the 查找以the开头的行 /end 查找以 查找以 查找以结尾的行 三、vi编辑器替换命令 1、语法: : s[范围,范围]str1/str2[g] g表示全…

如何在.NET中集成SignalR

SignalR 简介 SignalR是一个开放源代码库,可用于简化向应用添加实时Web功能,实时Web功能使服务器端代码能够将内容推送到客户端。 SignalR开源库:https://github.com/SignalR/SignalR SignalR 应用场景 需要高频次从服务器获取信息的应用&am…

Hack The Box-MagicGardens

总体思路 SMTP用户爆破->5000端口Docker注册表爆破->敏感数据泄露->Firefox远程调试LFI 信息收集&端口利用 nmap -sSVC 10.10.11.9目标开放了22、25、80、5000端口,先看80端口是否存在利用点 目录扫描结果大部分都是302跳转到admin界面,…

2.1色彩空间

色彩发送器 色彩认知 光源是出生点,光源发射出光线,光线通过直射反射折射等路径最终进入人眼。 但人眼接收到光线后,人眼的细胞产生了一系列化学反应。 由此把产生的信号传入大脑,最终大脑对颜色产生了认知感知。 光的要素 光…

基于STM32单片机老人体温心率血氧跌倒定位短信报警

一.硬件及设计功能 以STM32F103C8T6为中央处理器,GPS模块用采集数据,将数据发送给单片机后,单片机根据定位计算公式得出当前位置的经纬度信息和时间信息。经过LCD显示器处理后得出和时间信息SIM800模块发送短信到设定的手机号上,将…

安卓开发板_开发评估套件_4G/5G联发科MTK安卓主板定制开发

安卓开发板采用了联发科八核A53 CPU,主频2.0GHz,采用12nm制程工艺,拥有强大的通用计算性能。配备GE8300 GPU,支持1080P视频编码和H.264硬解码,能够解析目前流行的视频和图片格式,非常适合各种功能APP的测试…

社交变革:探索Facebook如何塑造我们的日常生活

在数字化时代的潮流中,社交媒体已经成为了我们日常生活中不可或缺的一部分,而Facebook作为其中的佼佼者,无疑扮演着至关重要的角色。本文将深入探讨Facebook在社交变革中所发挥的作用,以及它如何塑造着我们的日常生活。 1. 社交网…