系列十八、Spring bean线程安全问题

一、概述

        我们知道Spring中的bean,默认情况下是单例的,那么Spring中的bean是线程安全的吗?这个需要分情况考虑,bean中是否存在成员变量?bean中的成员变量是怎么处理的?...,针对bean的状态会有不同的处理方案:

        情况一:bean是单例的;

        情况二:bean是多例的(不会存在线程安全问题);

出现线程安全问题的原因:单实例bean中存在成员变量,并且有对这个bean进行读写的操作,因此出现了线程安全的问题。

二、演示Spring bean存在线程安全

2.1、UserService

/*** @Author : 一叶浮萍归大海* @Date: 2023/11/26 14:55* @Description: */
@Service
public class UserService {private String username;public String welcome(String name) {username = "welcome " + name;try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}return username;}}

2.2、MySpringConfig

/*** @Author : 一叶浮萍归大海* @Date: 2023/11/23 15:29* @Description:*/
@Configuration
@ComponentScan(basePackages = {"org.star"})
public class MySpringConfig {}

2.3、AopFullAnnotationMainApp

/*** @Author : 一叶浮萍归大海* @Date: 2023/11/23 15:14* @Description:*/
@Slf4j
public class AopFullAnnotationMainApp {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);UserService userService = context.getBean(UserService.class);Random r = new Random();String[] nameArray = new String[]{"张三", "李四", "王五", "赵六", "钱七"};for (int i = 1; i <= 5; i++) {new Thread(() -> {int index = r.nextInt(5);String name = nameArray[index];log.info("当前线程:{},当前索引:{},当前name的值:{},当前取出的值:{}", Thread.currentThread().getName(), index, name, userService.welcome(name));}, "线程" + i).start();}}}

三、解决方法

        上面代码演示了Spring中的bean的确存在着线程安全问题,出现问题我们要解决问题,针对Spring中bean中存在的线程安全,我们可以通过以下方式进行解决:

        方案一:将成员变量修改为局部变量(单例bean);

        方案二:使用ThreadLocal(单例bean);

        方案三:使用同步锁synchronized(单例bean);

        方案四:将单例bean设置为多例的;

        案例代码如下:

3.1、将成员变量修改为局部变量(单例bean)

3.1.1、UserService2

/*** @Author : 一叶浮萍归大海* @Date: 2023/11/26 14:55* @Description: 单例bean线程不安全(解决方式一:将成员变量修改为局部变量)*/
@Service
public class UserService2 {public String welcome(String name) {String username = "welcome " + name;try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}return username;}}

3.1.2、MySpringConfig(同上)

3.1.3、AopFullAnnotationMainApp 

/*** @Author : 一叶浮萍归大海* @Date: 2023/11/23 15:14* @Description:*/
@Slf4j
public class AopFullAnnotationMainApp {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);UserService2 userService2 = context.getBean(UserService2.class);Random r = new Random();String[] nameArray = new String[]{"张三", "李四", "王五", "赵六", "钱七"};for (int i = 1; i <= 5; i++) {new Thread(() -> {int index = r.nextInt(5);String name = nameArray[index];log.info("当前线程:{},当前索引:{},当前name的值:{},当前取出的值:{}", Thread.currentThread().getName(), index, name, userService2.welcome(name));}, "线程" + i).start();}}
}

3.2、使用ThreadLocal(单例bean)

3.2.1、UserService3

/*** @Author : 一叶浮萍归大海* @Date: 2023/11/26 14:55* @Description: 单例bean线程不安全(解决方式二:使用ThreadLocal)*/
@Service
public class UserService3 {private ThreadLocal<String> threadLocal = new ThreadLocal<>();public String welcome(String name) {threadLocal.set("welcome" + name);try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}return threadLocal.get();}}

3.2.2、MySpringConfig(同上)

3.2.4、AopFullAnnotationMainApp

/*** @Author : 一叶浮萍归大海* @Date: 2023/11/23 15:14* @Description:*/
@Slf4j
public class AopFullAnnotationMainApp {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);UserService3 userService3 = context.getBean(UserService3.class);Random r = new Random();String[] nameArray = new String[]{"张三", "李四", "王五", "赵六", "钱七"};for (int i = 1; i <= 5; i++) {new Thread(() -> {int index = r.nextInt(5);String name = nameArray[index];log.info("当前线程:{},当前索引:{},当前name的值:{},当前取出的值:{}", Thread.currentThread().getName(), index, name, userService3.welcome(name));}, "线程" + i).start();}}
}

3.3、使用同步锁synchronized(单例bean)

3.3.1、UserService4

/*** @Author : 一叶浮萍归大海* @Date: 2023/11/26 14:55* @Description: 单例bean线程不安全(解决方式三:使用同步锁synchronized)*/
@Service
public class UserService4 {private String username;public synchronized String welcome(String name) {username = "welcome " + name;try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}return username;}}

3.3.2、MySpringConfig(同上)

3.3.3、AopFullAnnotationMainApp 

/*** @Author : 一叶浮萍归大海* @Date: 2023/11/23 15:14* @Description:*/
@Slf4j
public class AopFullAnnotationMainApp {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);UserService4 userService4 = context.getBean(UserService4.class);Random r = new Random();String[] nameArray = new String[]{"张三", "李四", "王五", "赵六", "钱七"};for (int i = 1; i <= 5; i++) {new Thread(() -> {int index = r.nextInt(5);String name = nameArray[index];log.info("当前线程:{},当前索引:{},当前name的值:{},当前取出的值:{}", Thread.currentThread().getName(), index, name, userService4.welcome(name));}, "线程" + i).start();}}
}

3.4、将单例bean设置为多例的

3.4.1、UserService5

/*** @Author : 一叶浮萍归大海* @Date: 2023/11/26 14:55* @Description: 单例bean线程不安全(解决方式四:将单例bean设置为多例的)*/
@Scope("prototype")
@Service
public class UserService5 {private String username;public String welcome(String name) {username = "welcome " + name;try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}return username;}}

3.4.2、MySpringConfig(同上)

3.4.3、AopFullAnnotationMainApp 

/*** @Author : 一叶浮萍归大海* @Date: 2023/11/23 15:14* @Description:*/
@Slf4j
public class AopFullAnnotationMainApp {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);Random r = new Random();String[] nameArray = new String[]{"张三", "李四", "王五", "赵六", "钱七"};for (int i = 1; i <= 5; i++) {new Thread(() -> {UserService5 userService5 = context.getBean(UserService5.class);int index = r.nextInt(5);String name = nameArray[index];log.info("当前线程:{},当前索引:{},当前name的值:{},当前取出的值:{}", Thread.currentThread().getName(), index, name, userService5.welcome(name));}, "线程" + i).start();}}
}

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

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

相关文章

商品橱窗和抖音小店有什么区别?新手应该选择哪一个?

我是电商珠珠 在抖音小店内&#xff0c;有两种经营方式&#xff0c;一种是商品橱窗&#xff0c;还有一种是抖音小店。 很多人会将他们混之一谈&#xff0c;说开抖店需要粉丝&#xff0c;商品橱窗不用。 事实真的是这样吗&#xff1f; 接下来&#xff0c;我就来给大家讲讲二…

优化机器学习:解析数据归一化的重要性与应用

在机器学习中&#xff0c;数据归一化是一种数据预处理的技术&#xff0c;旨在将数据转换为相似的范围或标准化的分布。这样做的主要目的是消除不同特征之间的量纲差异或数值范围差异&#xff0c;以确保模型在训练时更稳定、更有效地学习特征之间的关系。 通常&#xff0c;机器…

【数据挖掘】国科大刘莹老师数据挖掘课程作业 —— 第三次作业

Written Part 1. 基于表 1 1 1 回答下列问题&#xff08;min_sup40%, min_conf75%&#xff09;&#xff1a; Transaction IDItems Bought0001{a, d, e}0024{a, b, c, e}0012{a, b, d, e}0031{a, c, d, e}0015{b, c, e}0022{b, d, e}0029{c, d}0040{a, b, c}0033{a, d, e}0038…

Django报错:RuntimeError at /home/ 解决办法

错误提示&#xff1a; RuntimeError at /home/ Model class django.contrib.contenttypes.models.ContentType doesnt declare an explicit app_label and isnt in an application in INSTALLED_APPS. 原因剖析&#xff1a; 博主在使用pycharm创建Django项目的时候&#xff0…

Jmeter和Testlink自动化测试框架研究与实施

摘 要 目前基于Jmeter的接口自动化测试框架&#xff0c;大多只实现脚本维护和自动调度&#xff0c;无法与Testlink进行互通&#xff0c;实现测试方案与自动化实施流程连接&#xff0c;本文基于Testlink、Jmeter、Jenkins实现&#xff1a;通过Testlink统一维护接口自动化测试用…

渲染到纹理:原理及WebGL实现

这篇文章是WebGL系列的延续。 第一个是从基础知识开始的&#xff0c;上一个是向纹理提供数据。 如果你还没有阅读过这些内容&#xff0c;请先查看它们。 NSDT在线工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - …

webpack external 详解

作用&#xff1a;打包时将依赖独立出来&#xff0c;在运行时&#xff08;runtime&#xff09;再从外部获取这些扩展依赖&#xff0c;目的时解决打包文件过大的问题。 使用方法&#xff1a; 附上代码块 config.set(externals, {vue: Vue,vue-router: VueRouter,axios: axios,an…

Spark on yarn 模式的安装与部署

任务描述 本关任务&#xff1a; Spark on YARN 模式的安装与部署。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; Spark 部署模式的种类&#xff1b;Spark on YARN 模式的安装。 Spark 部署模式 Spark 部署模式主要分为以下几种&#xff0c;Spark Stand…

Compose入门

​ 本篇文章主要是为了对Compose有一个初步了解。知道Compose是做什么的&#xff0c;用Compose能干什么&#xff0c;在目前的各种UI框架下面有些优势&#xff0c;参考Google官网的解释加上一些自己的理解生成的一篇文章。本人也是Compose初学者&#xff0c;通过每一步学习遇到哪…

系统频繁崩溃,如何考虑系统的稳定性和可扩展性?

最近网传互联网应用信息系统频繁崩溃&#xff0c;语雀崩完淘宝崩&#xff0c;淘宝崩完滴滴崩&#xff0c;随着业务的发展和技术的进步&#xff0c;对于信息系统的要求也越来越高。信息应用系统为了满足不断增长的用户和业务需求&#xff0c;提高系统的稳定性和扩展性至关重要。…

网络入门---网络的大致了解

目录标题 网络发展的简单认识协议作用的理解协议的本质什么是协议分层网络通信所面对的问题OSI七层模型TCP/IP模型协议报头的理解局域网通信局域网通信基本原理报头的问题局域网的特点跨网的网络链接如何查看mac地址 网络发展的简单认识 通过之前的学习我们知道计算机是给人提…

【深度学习】基于深度学习的超分辨率图像技术一览

超分辨率(Super-Resolution)即通过硬件或软件的方法提高原有图像的分辨率&#xff0c;图像超分辨率是计算机视觉和图像处理领域一个非常重要的研究问题&#xff0c;在医疗图像分析、生物特征识别、视频监控与安全等实际场景中有着广泛的应用。 SR取得了显著进步。一般可以将现有…

创建Asp.net MVC项目实现视图页面数据传值显示

MVC中视图传值 ViewData ViewBag TempData 举例创建三中传值方式实现页面数据展示 MVC中视图传值 Asp.net MVC中Controller向View传值有多种方式,这里简单说一下其中3种方式 ViewData、ViewBag和TempData ViewData ViewData存储数据&#xff0c;ViewData的声明和赋值方…

扫地机器人市场持续火爆,景联文科技数据采集标注方案助力扫地机器人智能化升级

随着消费者对智能家居和清洁卫生的需求增加&#xff0c;扫地机器人市场规模不断扩大。市场竞争也日益激烈&#xff0c;各品牌都在努力提升产品性能和服务质量&#xff0c;以获取更大的市场份额。 IDC的统计数据显示&#xff0c;今年双十一前两周&#xff08;2023年10月23日至20…

滴滴打车崩了!全过程

滴滴发布致歉10元补偿券&#xff0c;文末可领取 。 事情发生于 2023年11月27日晚~28日中午&#xff0c;滴滴打车服务出现大面积故障&#xff0c;登上微博热搜。 许多用户在使用滴滴出行时遇到了无法叫车、订单异常等问题&#xff0c;导致大量用户滞留在外&#xff0c;出行受阻…

吃火锅(Python)

题目描述 吃火锅 以上图片来自微信朋友圈&#xff1a;这种天气你有什么破事打电话给我基本没用。但是如果你说“吃火锅”&#xff0c;那就厉害了&#xff0c;我们的故事就开始了。 本题要求你实现一个程序&#xff0c;自动检查你朋友给你发来的信息里有没有 chi1 huo3 guo1。…

BUUCTF-pwn-ciscn_2019_ne_51

简单查看保护&#xff1a; 32为程序没有canary没有PIE&#xff0c;应该是简单的栈溢出。我们照着这个思路去找溢出点在哪&#xff0c;运行下程序看看什么情况&#xff1a; 程序上来是输入一个密码验证。随便输入下错误直接退出。因此我们需要到IDA中看看怎么回事&#xff1a; 主…

python -- python安装

1、python的诞生和发展&#xff1a; python语言是一种解释型、面向对象型、动态数据类型的高级程序设计语言。 2、python的安装&#xff1a; 1、安装解析器&#xff1a; 在安装的过程中需要注意的是&#xff1a; 在安装pycharm的时候也是同样的道理&#xff0c;需要指定安装…

【数据结构】——解决topk问题

前言&#xff1a;我们前面已经学习了小堆并且也实现了小堆&#xff0c;那么我们如果要从多个数据里选出最大的几个数据该怎么办呢&#xff0c;这节课我们就来解决这个问题。我们就用建小堆的方法来解决。 首先我们来看到这个方法的时间复杂度&#xff0c;我们先取前k个数据建立…

Egg.js中Cookie和Session

Cookie HTTP请求是无状态的&#xff0c;但是在开发时&#xff0c;有些情况是需要知道请求的人是谁的。为了解决这个问题&#xff0c;HTTP协议设计了一个特殊的请求头&#xff1a;Cookie。服务端可以通过响应头&#xff08;set-cookie&#xff09;将少量数据响应给客户端&#…