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来失效其他线程的变量
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电脑录屏怎么录?7个电脑录屏软件免费版强势来袭,赶快收藏!

电脑录屏怎么录?相信很多小伙伴们都不知道怎么在Windows电脑上录屏吧?在当今社会,随着互联网的快速发展,越来越多的小伙伴们开始通过制作视频内容来分享知识、展示技能或者记录生活。电脑录屏成为了一种简单高效的方式&#xff0c…

MarkDown语法使用手册

天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…

RabbitMQ详情

一.MQ简介 什么是MQ MQ本质是队列,FIFO先入先出,队列中存放的内容是message(消息),还是一种跨进程的通信机制,用于上下游传递消息。在互联网架构中是常见的上下游“逻辑解耦物理解耦”的消息通信服务。 主…

电脑突然提示:“failed to load steamui.dll”是什么情况?分享几种解决steamui.dll丢失的方法

相信有一些用户正在面临一个叫做“failed to load steamui.dll”的问题,这种情况多半发生在试图运行某个程序时,系统会提示一条错误消息:“failed to load steamui.dll”。那么,为何steamui.dll文件会丢失,又应该如何解…

cf练习5.29

A ac代码 #include<bits/stdc.h> #define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);using namespace std;int main() {IOSint t;cin>>t;while(t--){int ans0;int a,b;cin>>a>>b;if(b0){if(a%150) ansa/15;else ansa/151;}else if(b!0…

鸿蒙开发接口图形图像:【@ohos.window (窗口)】

窗口 窗口提供管理窗口的一些基础能力&#xff0c;包括对当前窗口的创建、销毁、各属性设置&#xff0c;以及对各窗口间的管理调度。 该模块提供以下窗口相关的常用功能&#xff1a; [Window]&#xff1a;当前窗口实例&#xff0c;窗口管理器管理的基本单元。[WindowStage]&…

Spring Cloud Gateway 集成 Nacos、Knife4j

目录 1、gateway网关配置1.1 pom 配置2.2 配置文件1.3 yaml 配置 2、其他服务配置2.1 pom 配置2.2 配置文件2.3 yaml 配置 3、界面访问4、其他 官方文档地址&#xff1a;Spring Cloud Gateway集成Knife4j 官方完整源码&#xff1a;https://gitee.com/xiaoym/swagger-bootstrap-…

扒出秦L三个槽点,我不考虑买它了

文 | Auto芯球 作者 | 雷慢 比亚迪的有一个王炸“秦L”&#xff0c;再一次吸引了我注意力&#xff0c; 我上一辆车刚卖不久&#xff0c;最近打算买第二辆车&#xff0c; 二手车和新车都有在看&#xff0c; 我又是一个坚定的实用主义者&#xff0c; 特别是现在的经济环境不…

P10-P11【重载,模板,泛化和特化】【分配器的实现】

三类模板&#xff08;类模板&#xff09;&#xff08;函数模板&#xff09;&#xff08;成员函数模板&#xff09; 特化 偏特化&#xff1a;模板参数个数/模板范围 定义的分配器 以上分配器的性能和内存管理有很大不足&#xff08;在分配内存时&#xff0c;会产生很大的内存开…

【C语言训练题库】杨辉三角(下三角型和金字塔型)

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 目录 题目&#xff1a;打印杨辉三角 1. 下三角型 1.1 图例: 1.2. 解析: 1.3. 代码: 1.4. 运行&#xff1a; 2. 金字塔型 2.1 图例 2.2. 解析 2.2.1. 打印金…

php 安装 swoole扩展

一 在swoole官网查询适配版本Swoole 文档 2. php环境为7.3下载 4.8 ​ wget https://pecl.php.net/get/swoole-4.6.6.tgztar -zxvf swoole-4.6.6.tgzcd swoole-4.6.6/usr/local/php7/bin/phpize​ ./configure --enable-openssl --enable-sockets --enable-mysqlnd --enabl…

HCIP-Datacom-ARST自选题库__MPLS多选【25道题】

1.下列描述中关于MPLS网络中配置静态LSP正确的是 当某一台LSR为Egress LSR时&#xff0c;1仅需配置In Label&#xff0c;范围为16~1023 当某一台LSR为Transit LSR时&#xff0c;需要同时配置In Label和Out label&#xff0c;In Label范围为16~1023&#xff0c;0utLabel范围为…

Swift 构造过程

构造过程 一、存储属性的初始赋值1、构造器2、默认属性值 二、自定义构造过程1、形参的构造过程2、形参命名和实参标签3、不带实参标签的构造器形参4、可选属性类型5、构造过程中常量属性的赋值 三、默认构造器结构体的逐一成员构造器 四、值类型的构造器代理五、类的继承和构造…

Vue——计算属性 computed 与方法 methods 区别探究

文章目录 前言计算属性的由来方法实现 计算属性 同样的效果计算属性缓存 vs 方法 前言 在官方文档中&#xff0c;给出了计算属性的说明与用途&#xff0c;也讲述了计算属性与方法的区别点。本篇博客只做自己的探究记录&#xff0c;以官方文档为准。 vue 计算属性 官方文档 …

接口测试系列(一)-什么是接口测试

接口测试系列 为什么要做这个事情&#xff1f; 对自己过往在接口测试上的经验&#xff0c;写一个小结的系列文章&#xff0c;是一个系统性的思考和知识构建。发布的同时&#xff0c;也是希望获得更多感兴趣的同学的意见和反馈&#xff0c;可以把这个部分做的更好。 系列入口&…

夏日采摘季,视频智能监控管理方案助力智慧果园管理新体验

5月正值我国各地西瓜、杨梅、大樱桃、油桃等水果丰收的季节&#xff0c;许多地方都举办了采摘旅游活动&#xff0c;吸引了众多游客前来体验采摘乐趣。随着采摘的人流量增多&#xff0c;果园的管理工作也面临压力。 为了提升水果园采摘活动的管理效果&#xff0c;减少人工巡查成…

nodejs版本管理切换工具nvm介绍、nvm下载、nvm安装、配置及nvm使用

最近很多同学问&#xff0c;在工作中&#xff0c;同时在进行2个或者多个不同的项目开发&#xff0c;每个项目的需求不同&#xff0c;进而不同项目必须依赖不同版本的NodeJS运行环境&#xff0c;这种情况下&#xff0c;对于维护多个版本的node将会是一件非常麻烦的事情&#xff…

SQL刷题笔记day6-1

1从不订购的客户 分析&#xff1a;从不订购&#xff0c;就是购买订单没有记录&#xff0c;not in 我的代码&#xff1a; select c.name as Customers from Customers c where c.id not in (select o.customerId from Orders o) 2 部门工资最高的员工 分析&#xff1a;每个部…

vue+elemntui 加减表单框功能样式

<el-form ref"form" :model"form" :rules"rules" label-width"80px"><el-form-item label"配置时间" prop"currentAllocationDate"><div v-for"(item,key) in timeList"><el-date…

高并发项目-用户登录基本功能

文章目录 1.数据库表设计1.IDEA连接数据库2.修改application.yml中数据库的名称为seckill3.IDEA创建数据库seckill4.创建数据表 seckill_user5.密码加密分析1.传统方式&#xff08;不安全&#xff09;2.改进方式&#xff08;两次加密加盐&#xff09; 2.密码加密功能实现1.pom.…