Java多线程面试重点-2

news2025/2/24 9:56:01

16.Synchronized关键字加在静态方法和实例方法的区别?

  • 修饰静态方法,是对类进行加锁(Class对象),如果该类中有methodA和methodB都是被Synch修饰的静态方法,此时有两个线程T1、T2分别调用methodA()和methodB(),则T2会阻塞等待直到T1执行完成之后才能执行。
  • 修饰实例方法时,是对实例进行加锁,锁信息在实例对象的对象头,如果调用同一个对象的两个不同的被Synch修饰的实例方法时,看到的效果和上面的一样,如果调用不同对象的两个不同的被Synch修饰的实例方法时,则不会阻塞。

17. CountDownLatch的用法?

  • 让主线程await,业务线程进行业务处理,处理完成时调用countDownLatch.countDown(),CountDownLatch实例化的时候需要根据业务去选择CountDownLatch的count。
  • 让业务线程await,主线程处理完数据之后进行countDownLatch.countDown(),此时业务线程被唤醒,然后去主线程拿数据,或者执行自己的业务逻辑。

18.解释一下volatile:

功能:

  • 保证线程可见性
  • 防止指令重排序

底层实现:

  • 可见性:
    • 被修饰的变量在被修改后可以立即同步到主内存,被修饰的变量在每次是用之前都从主内存刷新。JVM底层通过内存屏障来实现可见性。OS底层通过MESI(缓存一致性协议)。
    • 写内存屏障可以促使处理器将当前store buffer(存储缓存)的值写回主存。(先不记)
    • 读内存屏障可以促使处理器处理invalidate queue(失效队列),进而避免由于Store Buffer和Invalidate Queue的非实时性带来的问题。(先不记)
  • 禁止指令重排序:
    • 内存屏障来禁止指令重排序。
  • JMM内存屏障的策略:
    • 在每个volatile写操作的前面插入一个StoreStore屏障。
    • 在每个volatile写操作的后面插入一个StoreLoad屏障。
    • 在每个volatile读操作的前面插入一个LoadLoad屏障。
    • 在每个volatile读操作的后面插入一个LoadStore屏障。

使用场景(待完整总结,20231121):

根据经验总结,volatile最适合在一个线程写,其他线程读的场景。

19. 描述一下ThreadLocal的底层实现形式及实现的数据结构?

作用:

提供线程的局部变量,保证线程安全。使用不当会造成内存泄漏。

原理和数据结构:

  • ThreadLocal定义了ThreadLocalMap数据结构,它主要包含一个Entry类型的数组,Entry的keyThreadLocal本身(是弱引用),value为ThreadLocal对应添加的值。
  • 它通过key.threadLocalHashCode & (table.length – 1)确定数组索引位置,如果该位置的key不对,再通过nextIndex()计算下一个索引位置;它通过线性开放定址法减少hash冲突。
  • 每个线程(Thread类)都有一个ThreadLocalMap类型的threadLocals变量,存储这些局部变量(ThreadLocal对象)。

内存泄漏问题:

  • Entry的key是弱引用,在下一次GC后,就被回收了。此时,Map中存在key为null的Entry,ThreadLocal不会主动回收这些,可能会发生内存泄漏。
  • get、set、remove等方法都可以有清除key为null的Entry。

ThreadLocal碰撞解决与神奇的 0x61c88647:

  • 每次创建ThreadLocal实例时,哈希值都会累加 0x61c88647,目的是让哈希值能均匀的分布在2的N次方的数组里,减少碰撞。类似HashMap。

20. 线程池问题:

Executors提供了5种线程池:

  • newFixedThreadPool()(工作队列:LinkedBlockingQueue)
  • newCachedThreadPool()(工作队列: SynchronousQueue【同步移交队列,该队列没有缓冲区】、核心线程数为零、最大线程数为无限)
  • newSingleThreadExecutor()(工作队列:LinkedBlockingQueue)
  • newScheduledThreadPool()(工作队列:DelayedWorkQueue)
  • newSingleThreadScheduledExecutor()(工作队列:DelayedWorkQueue)

线程池参数:

  • int corePoolSize 线程池核心线程大小
  • int maximumPoolSize 线程池最大线程数量
  • long keepAliveTime 空闲线程存活时间
  • TimeUnit unit 空闲线程存活时间单位
  • BlockingQueue workQueue 工作队列
  • ThreadFactory threadFactory 线程工厂,主要用来创建线程(默认的工厂方法是:Executors.defaultThreadFactory()对线程进行安全检查并命名)
  • RejectedExecutionHandler handler 拒绝策略

4种拒绝策略:

当有界队列被填满后,拒绝策略(饱和策略)开始发挥作用。具体策略有:AbortPolicy中止策略(默认)、DiscardPolicy抛弃策略、DiscardOldestPolicy抛弃最旧的策略、CallerRunsPolicy调用者运行策略。

工作队列:

ArrayBlockingQueue、 LinkedBlockingQueue、SynchronousQueue、PriorityBlockingQueue、DelayedWorkQueue。

线程池执行顺序:

  • 默认情况下,创建完线程池后并不会立即创建线程,而是等到有任务提交时才会创建线程来进行处理。
  • 当线程数小于核心线程数时,每提交一个任务就创建一个线程来执行(即便当前有线程处于空闲状态),直到当前线程数达到核心线程数。
  • ... ...
  • 如果某个线程的空闲时间超过了keepAliveTime,将被标记为可回收的,并且当前线程池的当前大小超过了核心线程数时,这个线程将被终止。

线程池原理(execute()举例):

  • ctl变量(AtomicInteger):高3位表示线程池的生命周期,底29位表示线程池的线程容量。
    • 生命周期:RUNNING -1、SHUTDOWN 0 、STOP 1、TIDYING 2、TERMINATED 3
  • Worker对象底层也用到了AQS。
  • 也用到了ReentrantLock锁 --> mainLock。
  • 面试前,源码过一遍。

任务结束后会不会回收线程?

不会回收线程,线程会重复利用。

我通过源码了解:

  • 在getTask()中,会循环获取队列中任务,直到队列为空并且当前有效线程数量大于核心线程数量或者其他条件时,会减去有效线程数,结束循环,返回null。
  • 在runWorker()中,循环调用getTask()获取任务执行,如果getTask()==null结束循环,最后finally模块会调用processWorkerExit()回收Worker即工作线程。
    • processWorkerExit()中,completedAbruptly为true时,即出现异常时,会减去有效线程数。
    • processWorkerExit()是会将当前Worker回收。 如果线程异常结束,不能满足最小需要的线程数,就会添加,调用addWorker()

21. 什么叫做阻塞队列的有界和无界,实际中有用过吗?

有界与无界的概念:

  • 有界队列:固定大小的队列
  • 无界队列:没有设置固定大小的队列

具体队列:

  • ArrayBlockingQueue:
    • 一个由数组结构组成的有界阻塞队列。
    • 一把锁(ReentrantLock),不支持读写同时操作。
    • 可以实现生产者消费者模型(put()+take()),底层使用同一个锁的两个condition。
  • LinkedBlockingQueue:
    • 一个由链表结构组成的无界阻塞队列。
    • 入队使用一把锁(ReentrantLock),出队使用一把锁,支持读写同时操作。
    • 可以实现生产者消费者模型(put()+take()),底层使用两个锁的condition。
  • PriorityBlockingQueue:
    • 一个支持优先级排序的无界阻塞队列。
    • 大堆、小堆,实现compareTo。
  • DelayQueue:
    • 一个使用优先级队列实现的无界阻塞队列,可以实现精确的定时任务。
  • SynchronousQueue:
    • 一个不存储元素的阻塞队列。
  • LinkedTransferQueue:
    • 一个由链表结构组成的无界阻塞队列。
    • 它是LinkedBolckingQueue和SynchronousQueue的合体。生产者会一直阻塞,直到所添加到队列的元素被某一个消费者所消费。
  • LinkedBlockingDeque:
    • 一个由链表结构组成的双向无界阻塞队列。
    • 可以用在“工作窃取”模式中 -> ForkJoinPool。

22. 如何在方法栈中进行数据传递?

  • 通过方法参数传递。
  • 通过共享变量。
  • 如果在用一个线程中,还可以使用ThreadLocal进行传递。

23. 描述一下AQS?****

简介(AbstractQueuedSynchronizer):

AQS是一个用于构建锁和同步器的框架。它是除了java自带的synchronized关键字之外的锁机制。例如ReentrantLock、ReentrantReadWriteLock、Semaphore、FutureTask等都是基于AQS实现的。

状态变量state:

AQS中定义了一个状态变量state,特点:volatile变量修饰,CAS方式更新。

它的两种使用方法:(拓展时说)

  • 互斥锁:
    • 当AQS只实现为互斥锁的时候,每次只要原子更新state的值从0变为1成功了就获取了锁,可重入是通过不断把state原子更新加1实现的。
  • 互斥锁 + 共享锁:
    • 当AQS需要同时实现为互斥锁+共享锁的时候,低16位存储互斥锁的状态,高16位存储共享锁的状态,主要用于实现读写锁。

AQS队列(CLH队列):

是一个FIFO的双向队列,AQS依赖它来完成同步状态的管理,CLH队列包含多个Node对象,每个节点表示一个线程,它保存着线程的引用(thread)、状态(waitStatus)、前驱节点(prev)、后继节点(next)、条件队列中的后继节点(nextWaiter)。

获取锁失败(非tryLock())的线程都将进入这个队列中排队,等待锁释放后唤醒下一个排队的线程(互斥锁模式下)。

AQS队列的头结点不为空,头结点是加锁成功的节点,在设置成头节点后,会将该节点的线程设置为null。

waitStatus值:CANCELLED= 1、SIGNAL=-1、CONDITION=-2、PROPAGATE=-

Condition队列:

内部类ConditionObject,它实现了Condition接口,主要用于实现条件锁。

ConditionObject中也维护了一个队列,这个队列主要用于等待条件的成立,当条件成立时,这个队列中的元素将其移动到AQS的队列中,等待占有锁的线程释放锁后被唤醒。

Condition典型的运用场景:在BlockingQueue中的实现,当队列为空时,获取元素的线程阻塞在notEmpty条件上,一旦队列中添加了一个元素,将通知notEmpty条件,可从阻塞队列中获取元素。

模板方法:

AQS里面定义了一系列的模板方法,我们只需重新部分钩子方法就可以,比如下面这些:

  • isHeldExclusively():该线程是否正在独占资源(只有用到condition需实现)。
  • tryAcquire(int):独占方式,尝试获取资源。成功true,失败false。
  • tryRelease(int):独占方式,尝试释放资源。成功true,失败false。
  • ... ...

常用的方法:

  • acquire(int):独占模式的获取,忽略中断。
  • acquireInterruptibly(int):独占模式的获取,可中断
  • release(int):独占模式的释放。
  • ... ...

源码:

面试前,源码过一遍,这个简单过一下,感觉没啥问的。

24. 简要描述一下ConcurrentHashMap底层原理?

JDK1.7:

  • 分段锁:内部主要是一个Segment数组,而数组的每一项又是一个HashEntry数组,元素都存在HashEntry数组里。因为每次锁定的是Segment对象,也就是整个HashEntry数组,所以又叫分段锁。
  • 计算Segment数组位置:

  • ConcurrentHashMap默认长度是16,即有16个Segment,最大支持16个线程并发。

JDK1.8:*****

  • ConcurrentHashMap舍弃了分段锁的实现方式,利用CAS + synchronized + volatile(关键变量,例如table、nextTable、sizeCtl)来保证并发更新的安全。
  • 底层数据结构:数组+链表+红黑树来实现。
  • 重要成员变量:
    • table:默认为null,初始化发生在第一次插入操作,用来存储Node节点数据。
    • nextTable:默认为null,扩容时新生成的数组,其大小为原数组的两倍。
    • sizeCtl :默认为0,用来控制table的初始化和扩容操作。
      • 1:代表table正在初始化
      • N:表示有N-1个线程正在进行扩容操作
    • Node:保存key,value及key的hash值的数据结构(其中value和next都用volatile修饰)。
  • put过程简述:
    • put操作采用CAS+synchronized实现并发插入或更新操作:
      • 当前bucket为空时,使用CAS操作,将Node放入对应的bucket中。
      • 出现hash冲突,则采用synchronized关键字。
        • 倘若当前hash对应的节点是链表的头节点,遍历链表,若找到对应的node节点,则修改node节点的值,否则在链表末尾添加node节点;
        • 倘若当前节点是红黑树的根节点,在树结构上遍历元素,更新或增加节点。
      • 倘若当前map正在扩容(f.hash == MOVED),先协助扩容,在更新值。

ConcurrentHashMap 不允许key value 为空。 -> null 是特殊值,充当了所有非标量归约运算的隐式基础。

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

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

相关文章

http穿透怎么做?

众所周知http协议的默认端口是80,由于国家工信部要求,域名必须备案才给开放80端口,而备案需要固定公网IP,这就使得开放http80端口的费用成本和时间成本变的很高。那么能不能利用内网穿透技术做http穿透呢?下面我就给大…

Stability AI最新的SD3模型存在严重问题 为规避裸体结果导致躯体部分错乱

人工智能 Stability AI 最新的 SD3 Medium 模型存在严重问题,只要生成人物就会出现躯体错乱,这似乎是该公司刻意规避生成裸体图片的结果。目前猜测他们可能在训练过程中就剔除了 NSFW 内容,同时在训练时规避裸体内容进而导致模型也会刻意将人…

Haption Virtuose 6D力反馈设备遥操作机器人应用研究

在虚拟现实和远程操作技术的飞速发展下,力反馈设备成为了一个不可或缺的工具。其中,Haption Virtuose 6D力反馈设备以其卓越的性能和广泛的应用领域,成为了这一领域的佼佼者。本文将详细介绍Haption Virtuose 6D力反馈设备及其在遥操作机器人…

Flutter系列:关于ensureInitialized()

Flutter系列 关于ensureInitialized() - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28…

RBAC权限实战

一、项目结构说明、搭建以及初步验证 引入SSM框架依赖: <dependencies> <dependency> <groupId>javax.servlet…

原型模式(大话设计模式)C/C++版本

原型模式 C 参考&#xff1a;https://www.cnblogs.com/Galesaur-wcy/p/15924300.html #include <iostream> #include <string> using namespace std;class WorkExprerience { private:string workDate;string company;public:WorkExprerience() {}~WorkExprerie…

《站在2024年的十字路口:计算机专业是否仍是高考生的明智之选?》

文章目录 每日一句正能量前言行业竞争现状行业饱和度和竞争激烈程度[^3^]新兴技术的影响[^3^]人才需求的变化[^3^]行业创新动态如何保持竞争力 专业与个人的匹配度判断专业所需的技术能力专业核心课程对学生的要求个人兴趣和性格特点专业对口的职业发展要求实践和经验个人价值观…

redis的四种模式部署应用

这里写目录标题 redis应用redis单机部署redis主从redis哨兵Cluster模式 redis应用 redis单机部署 关闭防火墙[rootzyq ~]#: yum -y install wget make gcc gcc-c ...... [rootzyq ~]#: wget https://download.redis.io/redis-stable.tar.gz --2024-01-01 19:41:14-- https:/…

qemu创建kvm虚拟机-x86模拟arm

1、虚拟机环境 虚拟机ubuntu22.042、下载需要的依赖 apt install openssh-server net-tools vim -yapt install qemu qemu-kvm qemu-system-arm bridge-utils uml-utilities qemu-efi-aarch64 cloud-image-utils -y#查看版本 qemu-img -V(1) 下载uefi固件 cd /optwget https…

tcp协议机制的总结(可靠性,提高性能),基于tcp的应用层协议,用udp如何实现可靠传输

目录 总结 引入 可靠性 ​编辑 分析 三次握手 提高性能 其他 常见的基于tcp应用层协议 用udp实现可靠传输 总结 引入 为什么tcp要比udp复杂的多? 因为它既要保证可靠性,又要兼顾性能 可靠性 分析 其中,序列号不止用来排序,还可以用在重传时去重 确认应答是机制中的…

中小制造业工厂要不要上MES系统

MES系统的主要功能包括制造数据管理、计划排产管理、生产调度管理、库存管理、质量管理、人力资源管理、工作中心/设备管理、工具工装管理、采购管理、成本管理、项目看板管理、生产过程控制、底层数据集成分析、上层数据集成分解等。通过这些模块&#xff0c;MES为企业打造一个…

前端菜鸡流水账日记 -- pnpm的学习

哈咯哇大家&#xff0c;我又来了&#xff0c;最近稍微悠闲一些&#xff0c;所以就趁着这个机会学习一些新的知识&#xff0c;今天就是碰巧遇到了pnm&#xff0c;这个可以看作是npm的升级版本&#xff0c;比npm要快&#xff0c;用起来也更得劲更迅速 官网地址&#xff1a;https…

Java ORM 双雄:Mybatis vs Hibernate 的技术对决

引言&#xff1a;本文将对 MyBatis 和H ibernate 进行全面比较&#xff0c;探讨它们在各个方面的异同以及在实际项目中的应用场景。我们将从基本概念、工作原理、配置方式、性能表现、灵活性、学习曲线等多个方面进行比较&#xff0c;帮助读者更好地理解并选择适合自己项目需求…

每日一题——Python实现PAT乙级1028 人口普查 Keyboard(举一反三+思想解读+逐步优化)六千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 题目链接​编辑我的写法 专业点评 时间复杂度分析 空间复杂度分析 总结 我要更强…

Windows 11 中安装 Docker Desktop 并安装镜像

本该主要介绍在 Windows 11 中安装 Docker Desktop 时的一些准备工作&#xff0c;以及该如何下载和安装&#xff0c;然后分别使用管理界面和 Docker 命令安装两个镜像。 一、准备工作 在 Windows 11 中安装 Docker Desktop 前&#xff0c;需要做一些准备。打开 【Windows 功能…

R语言数据分析案例28-对数据集可视化和T检验

一、分析主题&#xff1a; 本分析旨在对数据集进行可视化和 T 检验&#xff0c;以探索数据集中的变量之间的关系和差异。通过可视化数据&#xff0c;我们可以直观地了解数据的分布和趋势&#xff0c;而 T 检验则可以帮助我们确定这些差异是否具有统计学意义。 二、具体分析 …

【CS.AL】算法必学之贪心算法:从入门到进阶 —— 关键概念和代码示例

文章目录 1. 概述2. 适用场景3. 设计步骤4. 优缺点5. 典型应用6. 题目和代码示例6.1 简单题目&#xff1a;找零问题6.2 中等题目&#xff1a;区间调度问题6.3 困难题目&#xff1a;分数背包问题 7. 题目和思路表格8. 总结References 1000.1.CS.AL.1.4-核心-GreedyAlgorithm-Cre…

ATF是如何完成双系统切换的?

ATF&#xff08;Arm Trusted Firmware&#xff09;是一个用于ARM架构处理器的可信固件&#xff0c;它最初提供的最主要的功能就是&#xff1a;双系统切换和电源管理。 那么如何进行双系统切换呢&#xff0c;在双系统切换的示例中&#xff0c;除了CPU的跳转&#xff0c;例如CPU…

【面试干货】Java集合类详解:List、Set、Queue、Map、Stack的特点与用法

【面试干货】Java集合类详解&#xff1a;List、Set、Queue、Map、Stack的特点与用法 1、Map1.1 特点1.2 用法1.3 常见的实现类 2、Set2.1 特点2.2 用法2.3 常见的实现类 3、List3.1 特点3.2 用法3.3 常见的实现类 4、Queue4.1 特点4.2 用法4.3 常见的实现类 5、Stack5.1 特点5.…

瀑布流布局:图片浏览页面

目录 任务描述 相关知识 HTML(HyperText Markup Language) 瀑布流布局&#xff1a; 题目 任务描述 在本关中&#xff0c;你的任务是理解瀑布流布局&#xff0c;以展示多张图片。瀑布流布局使得图片能够按照设定的列数依次排列&#xff0c;每列的高度会根据图片的高度自动调…