【两万字面试系列】三年前的面试题。Service里面的线程安全问题

前言

三年前,大概是21年,那会刚学完java,然后去面试,被打的一塌糊涂,今天来盘一盘之前的面试,到底是怎样的问题整住了。然后发现了去年整的线程安全东西,也贴到文章后面了。那个贴的还不太准,慢慢完善!会整完然后发B站视频。
在这里插入图片描述

线程安全

其实简单的来看就是线程安全的问题。现在来看这些问题好像没有什么,就是比较正常的问题。但是当时掌握的确实太不好了,然后可能面试官看我太菜了,这些回答不上来就没有接着往后续问了。大家看到这个面试题会想到什么呢,会想怎么回答和解决呢。
也可以结合一个实际的项目区演示和测试一番。写一个数字的成员变逻辑写计算然后看结果。

在Spring Boot中,处理Service层的线程安全问题是非常重要的,因为Spring的Service默认是单例的,这意味着Spring容器中只会创建一个Service实例。如果Service中包含了状态(即成员变量),那么在并发环境下可能会出现线程安全问题。以下是一些处理Service层线程安全问题的建议:

  1. 避免在Service中定义有状态的成员变量

尽量不要在Service中定义有状态的成员变量。如果确实需要存储状态,考虑将这些状态存储在方法内部的局部变量中,因为局部变量是线程安全的,它们存储在每个线程自己的栈中。
2. 使用线程安全的类

如果Service需要维护跨方法调用的状态,应该使用线程安全的类或数据结构,如ConcurrentHashMap、AtomicInteger等。
3. 同步访问共享资源(使用锁机制)

当多个线程需要访问同一个资源时,可以通过同步机制来保证线程安全。可以使用synchronized关键字或java.util.concurrent.locks包中的锁机制。但是,过度同步可能会导致性能问题,因此需要谨慎使用。
4. 使用ThreadLocal

ThreadLocal可以为每个线程提供一个变量的副本,使每个线程都有自己独立的变量副本,从而避免线程安全问题。但是,使用ThreadLocal时需要注意及时清理,避免内存泄漏。

  1. 使用@Scope注解(不建议)

如果确实需要Service有状态,可以考虑使用Spring的@Scope注解来改变Bean的作用域。例如,使用@Scope(“prototype”)注解可以让Spring容器为每个请求创建一个新的Service实例,这样可以避免多个请求共享同一个Service实例的线程安全问题。但这种方式会增加对象的创建和销毁的开销。

线程安全

在这里插入图片描述

后面是自己写的,还不是很完善,会补充的完善,然后B站发视频

3.线程方面

3.1线程安全
3.1. spring如何处理线程并发问题

spring的对象是默认是单例的。如果在里面声明成员变量的话。然后一个请求创建一个线程,多个线程同时请求一个资源就会出现问题。(单例bean是线程安全的)

解决方式有两种

1.将spring声明成多例

2.使用threadloacal

3.在代码块中加入同步锁 让他编程同步的 就可以解决了

相当于把并行编程了串行,会影响服务器他吞吐量。

4.成员变量声明在方法里面

3.2 tomcat线程模型

tomcat也已经支持异步了;但是他的效率比netty这种肯定还是要低的。

BIO :tomcat6默认采用的。每个请求都要创建一个线程来处理,线程开销较大,不能处理高并发

3.4 Volatile

涉及到可见性 ,禁止重排序

volatile与cas 通过乐观锁的思想来共同完成相应的reenTrankllock,具体在锁那块3.4里面有

3.5 Servlet

单实例 ,多线程

3.6 ThreadLocal

以空间换时间,给每个线程分配一个空间

ThreadLocal 是Java里一种特殊的变量。每个线程都有一个 ThreadLocal 就是每个线程都拥有了自己独立的一个变量,竞争条件被彻底消除了。如果为每个线程提供一个自己独有的变量拷贝,将大大提高效率。首先,通过复用减少了代价高昂的对象的创建个数。其次,你在没有使用高代价的同步或者不变性的情况下获得了线程安全。

3.7 ThreadLocal可能引发内存泄漏问题

1、强引用(StrongReference)
最普遍的一种引用方式,如String s = “abc”,变量s就是字符串“abc”的强引用,只要强引用存在,则垃圾回收器就不会回收这个对象。
2、软引用(SoftReference)
用于描述还有用但非必须的对象,如果内存足够,不回收,如果内存不足,则回收。一般用于实现内存敏感的高速缓存,软引用可以和引用队列ReferenceQueue联合使用,如果软引用的对象被垃圾回收,JVM就会把这个软引用加入到与之关联的引用队列中。
3、弱引用(WeakReference)
弱引用和软引用大致相同,弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。当一个对象既有弱引用又有强引用的时候不会清楚弱引用。短时间内通过弱引用取对应的数据,可以取到,当执行过第二次垃圾回收时,将返回null。弱引用主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器标记。
ThreadLocal采用的是弱引用的key,当没有强引用来使用Thread Local的key时,key就会被回收。当我把ThreadLocal比作一个水桶,水桶上面有一个桶盖,我们在寻找桶的时候通过桶盖来寻找,但是当没有人惦记桶的时候,桶盖会自己丢失,这样我们没办法找到桶,也没法使用桶里的东西,这样就会导致内存泄漏。

 static class ThreadLocalMap {static class Entry extends WeakReference<ThreadLocal<?>> {/** The value associated with this ThreadLocal. */Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}}}
	TreadLocalMap的Entry继承了WeakReference<ThreadLocal<?>>,即Entry的key是弱引用(该引用只存在弱引用的情况下,下一次GC]

ThreadLocal在保存的时候会把自己当做Key存在ThreadLocalMap中,正常情况应该是key和value都应该被外界强引用才对,但是现在key被设计成WeakReference弱引用了。

ThreadLocal的 key若引用 容易被GC回收,然后变成null。导入里面的 值没法被访问到,容易产生内存泄漏

3、解决方法

想象情况:如果一个线程被回收了,然后线程里面的成员变量也被回收,就没有内存泄漏的问题了。

实际情况:一般使用线程池,线程池是重复利用的,会存在内存泄漏的问题。ThreadLocal在进行数据读写的时候默认会进行一些清理的操作,找到并清理Entry里面key 为null 的数据

这个没有太好的解决方案,只能通过规范代码使用来解决最好是每次使用完ThreadLocal后,主动调用remove 方法去移除数据,把ThreadLocal 声明成全局变量,使他无法被GC回收

所以为了避免内存泄漏,在ThreadLocal使用结束以后,规范操作,执行下remove方法。

或者你可以从ThreadLocal,引出底层的Weak引用话题,再引出JVM结构以及OOM调优方面的话题。*

3.2 main方法线程(jvm创建线程过程)

一个程序创建一个jvm实例,一个进程,然后开辟一个线程

img

程序运行

JVM 在启动的时候会创建一个 VM Thread,这是所有线程的祖先,其他的线程都是由这个线程派生出去的。

在 Java 中,线程分为两种:普通线程守护线程

普通线程就是通常业务逻辑执行的代码,代码执行完成之后,普通线程也就退出了。而守护线程一般运行在后台,比如说响应命令行的操作,守护线程会在普通线程退出之后退出。

当程序执行完成之后,JVM 也要退出,程序执行完的标志就是非守护线程都退出了。当所有的非守护线程退出之后,守护线程也会退出。

程序在执行完成之后,会调用 System.exit() 方法,然后虚拟机退出,程序彻底结束。

exit 方法接收一个整型的参数,如果传入的值为 0,那么就表示程序是正常退出的,如果是任何非零的值,那么就表示是异常退出。

其实在代码中,非常不推荐调用这个方法,因为这个方法会造成一些意向不到的情况。

作者:Rayjun
链接:https://juejin.cn/post/6866744930376220679
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

3.3线程池

线程池的几个参数

包括阻塞队列这种

3.3.1线程池几大参数
3.3.1队列

无界队列oom

3.4锁

同步块大家都比较熟悉,通过 synchronized 关键字来实现;所有加上 synchronized 的方法和块语句,在多线程访问的时候,同一时刻只能有一个线程能够访问。

ConcurrentHashMap的锁

jdk1.8 使用到了 CAS+Volatile

synchronized+volatile(1.8版本)

CAS+Volatile

心想,确实是可以实现的呀!因为 AbstractQueuedSynchronizer(简称 AQS)内部就是通过 CAS + volatile(修饰同步标志位state) 实现的同步代码块。

volatile 保证了可见性和有序性,

cas 保证了原子性,像i++是三个操作,普通的保证不了这三个操作一起执行,然后使用cas 保证原子性。优点是可以保障原子性,但是缺点是有时候自旋时间太长,也会有问题。

AQS

AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它,如常用的ReentrantLock。 简单来说,AQS定义了一套框架,来实现同步类

AQS的核心思想是对于共享资源,维护一个双端队列来管理线程,队列中的线程依次获取资源,获取不到的线程进入队列等待,直到资源释放,队列中的线程依次获取资源。 AQS的基本框架如图所示:

AQS定义了一个实现同步类的框架,实现方法主要有tryAquiretryRelease,表示独占模式的资源获取和释放,tryAquireSharedtryReleaseShared表示共享模式的资源获取和释放。 源码分析如上文所述。

ReenTrankLock 锁
synchronized 锁对象头
Mysql的锁

表锁 行锁

CAS加volitale实现同步代码块,然后应用有 AQS ,

3.5 多线程 生产者与消费者

生产者 - 消费者模型 Producer-consumer problem 是一个非常经典的多线程并发协作的模型,在分布式系统里非常常见。

public void run() {synchronized (queue) {while (queue.size() == maxCapacity) { //一定要用 while,而不是 if,下文解释try {System.out.println("生产者" + Thread.currentThread().getName() + "等待中... Queue 已达到最大容量,无法生产");wait();System.out.println("生产者" + Thread.currentThread().getName() + "退出等待");} catch (InterruptedException e) {e.printStackTrace();}}if (queue.size() == 0) { //队列里的产品从无到有,需要通知在等待的消费者queue.notifyAll();}Random random = new Random();Integer i = random.nextInt();queue.offer(new Product("产品"  + i.toString()));System.out.println("生产者" + Thread.currentThread().getName() + "生产了产品:" + i.toString());}}作者:小齐本齐
链接:https://juejin.cn/post/6872131047032553486
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

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

相关文章

如何在Jupyter Notebook切换conda虚拟环境

大家好我是咕噜美乐蒂&#xff0c;很高兴又和大家见面了&#xff01;在 Jupyter Notebook 中切换 Conda 虚拟环境可以通过以下步骤完成。首先&#xff0c;确保您已经安装了 Conda&#xff0c;并且创建了多个虚拟环境。接下来&#xff0c;我将详细介绍在 Jupyter Notebook 中如何…

【大数据面试题】012 谈谈 Hive 性能优化常用的方法

一步一个脚印&#xff0c;一天一道面试题 数据分区和分桶&#xff1a;合适的分区和分桶能减少数据量的输入 合适的数据格式&#xff1a;Parquet&#xff0c;ORC 是可以减少 I/O &#xff0c;网络传输速率等的 列裁剪&#xff1a;一般不要使用 SELECT *&#xff0c;只获取真正…

设计模式:行为型模式

行为型设计模式是一类设计模式&#xff0c;它们关注的是对象之间的相互作用&#xff0c;以及对象如何通过消息传递来实现松耦合。这些模式涉及到算法和对象之间职责的分配。在本文中&#xff0c;我们将深入探讨几种常见的行为型模式&#xff0c;并提供详细的解释、示例和应用场…

HQL,SQL刷题,尚硅谷

目录 相关表数据&#xff1a; 题目及思路解析&#xff1a; 查询结果排序&分组指定条件 1、查询学生的总成绩并按照总成绩降序排序 2、按照如下格式显示学生的语文、数学、英语三科成绩&#xff0c;没有成绩的输出为0&#xff0c;按照学生的有效平均成绩降序显示 3、查询一…

hosts.allow限制可通过SSH登录到服务器的IP

hosts.allow限制可通过SSH登录到服务器的IP 网络防火墙是阻挡非授权主机访问网络的第一道防护&#xff0c;但是它们不应该仅有一道屏障。Linux使用了两个文件!。/etc/hosts.allow和/etc/hosts.deny&#xff0c;根据网络请求的来源限制对服务的访问。 hosts.allow文件列出了允…

常用SQL查询方法与实例

目录 SELECT查询 INSERT查询 UPDATE查询 DELETE查询 JOIN查询 GROUP BY查询 HAVING查询 窗口函数 公共表表达式&#xff08;CTEs&#xff09; 递归查询 透视表 分析函数 解透视 条件聚合 日期函数 合并语句 情况语句 常用SQL查询方法有以下几种&#xff1a; S…

【无监督学习之聚类】

曾梦想执剑走天涯&#xff0c;我是程序猿【AK】 目录 简述概要知识图谱1. K-Means聚类2. 层次聚类&#xff08;Hierarchical Clustering&#xff09;3. DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff09;4. 谱聚类&#xff08;Spect…

一个实时波形图的封装demo(QT)(qcustomplot)

前言&#xff1a; 封装的一个实时波形图的类&#xff0c;可以直接提升使用。 提供了接口&#xff0c;可以更改颜色&#xff0c;样式&#xff0c;等等 参考&#xff1a; Qt Plotting Widget QCustomPlot - Introduction 另外参考了一个大神的作品&#xff0c;链接没找到。 项目…

前端面试练习24.2.29

一.关于Vuex说法 Vuex可以用来管理数据 Vuex也可以实现组件间的传值 mutation中的方法按照规定最好不要涉及异步方法 Vuex的属性有 state 存储状态 mutations 同步函数 actions 异步函数&#xff0c;并且调用的事mutations getters 派生状态&#xff0c;类似与vue中的c…

嘎嘎快充云快充互联互通系统使用说明书

嘎嘎快充云快充互联互通系统 V1.0.0 使用手册 &#xff08;V1.0&#xff09; 二○二四年一月 目录 一、软件产品概述 2 二、系统要求及运行环境 2 1、 系统要求 2 2、 运行环境 3 三、软件操作和说明 3 1、 软件的安装 3 2、 软件启动 8 3、 软件工作界面 8 4、 软件功能介绍…

#13Maven打包生成MD5校验文件的两种方式

目录 1、checksum-maven-plugin 2、maven-antrun-plugin 1、checksum-maven-plugin <plugin><groupId>net.ju-n.maven.plugins</groupId><artifactId>checksum-maven-plugin</artifactId><version>1.2</version><executions&g…

线路覆冰加重导线舞动风险,输电线路导线舞动在线监测装置保障运行安全

2月21日&#xff0c;山东烟台迎来强降雪天气&#xff0c;国网烟台供电公司紧急部署&#xff0c;组织运维人员联合智能巡检设备对重要变电站和输电线路进行巡视&#xff0c;确保电网安全稳定运行。 “雨雪天气给输电线路造成一定的影响&#xff0c;尤其是雨雪加上冰冻&#xff0…

NIST正式发布网络安全框架 2.0最终版:相比之前两个版本的六大重大变化

2月26日美国国家标准与技术研究院 (NIST) 正式发布了更新后的网络安全框架 (CSF)&#xff0c;这是其降低网络安全风险的里程碑式指导文件。新的 2.0 版本专为所有行业部门和组织类型而设计&#xff0c;从最小的学校和非营利组织到最大的机构和公司&#xff0c;无论其网络安全的…

Nodejs+vue汽车保养美容管理系统vscode前后端分离项目

汽车美容保养管理系统后台采用nodejs语言开发,前台页面和后台管理页面使用vue等技术开发,使用MySql作为数据持久化存储工具对汽车美容保养管理系统的用户等角色权限对应的功能等进行存储。采用vsocde集成IDE对汽车美容保养管理系统统进行开发,整合系统的各个模块。 拟开发的汽车…

Kivy和BeeWare 开发APP的优缺点,及其发展历史

Kivy和BeeWare都是流行的Python框架&#xff0c;用于开发移动应用。它们各自有独特的特点和优势&#xff0c;同时也面临一些挑战和限制。下面是对这两个框架的开发优缺点及其发展历史的总结。 Kivy 发展历史 起源&#xff1a;Kivy诞生于2010年&#xff0c;旨在提供一个用于P…

[回归指标]R2、PCC(Pearson’s r )

R2相关系数 R2相关系数很熟悉了&#xff0c;就不具体解释了。 皮尔逊相关系数&#xff08;PCC&#xff09; 皮尔逊相关系数是研究变量之间线性相关程度的量&#xff0c;R方和PCC是不同的指标。R方衡量x和y的接近程度&#xff0c;PCC衡量的是x和y的变化趋势是否相同。R方是不…

Mac OS 制作可引导安装器并重新安装系统

Mac 使用 U盘或移动固态硬盘制作可引导的安装器&#xff08;以 Monterey 为例&#xff09; 本教程参考 Apple 官网相关教程 创建可引导 Mac OS 安装器 重新安装 Mac OS 相关名词解释 磁盘分区会将其划分为多个单独的部分&#xff0c;称为分区。分区也称为容器&#xff0c;不同…

以太坊学习工具推荐

以太坊学习工具推荐 主网浏览器Sepolia测试网浏览器ETH官方网站Raw Transaction Decode Toolweb3.pyweb3.jsSolidity 学习文档

Windows PowerShell 命令行历史记录补全

Windows 命令行历史记录补全 使用 powershell 安装PSReadLine 2.1.0 Install-Module PSReadLine -RequiredVersion 2.1.0检查是否存在配置文件 Test-path $profile # 为 false 则执行命令创建 New-item –type file –force $profile编辑配置文件 notepad $profile# 输入如下…

备战蓝桥杯---树形DP基础3

上一次我们讲了二叉苹果树&#xff0c;现在我们加一点难度&#xff0c;从二叉变成了多叉苹果树。 这样子我们就不可以直接按照上次的方法DP&#xff0c;我们其实可以发现&#xff0c;我们可以用类似背包的思想求解&#xff0c;这就是所谓的树上背包。 我们先加进第一个儿子来…