多线程访问Servlet如何谨慎处理共享资源

1. 避免共享状态(最佳实践)

  • 核心思想:Servlet 本身应设计为无状态(Stateless),不依赖实例变量存储请求相关数据。

  • 实现方式

    • 将变量声明在方法内部(局部变量),每个线程独享栈内存。

    • 若需跨请求传递数据,使用请求作用域(HttpServletRequest)或会话作用域(HttpSession)。

  • 示例

    public class SafeServlet extends HttpServlet {// ❌ 危险:实例变量被所有线程共享// private int counter;protected void doGet(HttpServletRequest req, HttpServletResponse resp) {// ✅ 安全:局部变量,线程独享int localCounter = 0;localCounter++;resp.getWriter().write("Count: " + localCounter);}
    }

2. 使用线程安全的数据结构

  • 适用场景:必须共享资源时(如全局计数器、缓存)。

  • 实现方式

    • 使用 java.util.concurrent 包中的线程安全类:
      ConcurrentHashMapAtomicIntegerCopyOnWriteArrayList 等。

    • 避免直接使用非线程安全的类(如 HashMapArrayList)。

  • 示例

    public class CounterServlet extends HttpServlet {// ✅ 线程安全计数器private AtomicInteger atomicCounter = new AtomicInteger(0);protected void doGet(HttpServletRequest req, HttpServletResponse resp) {int count = atomicCounter.incrementAndGet();resp.getWriter().write("Atomic Count: " + count);}
    }

3. 同步(Synchronization)

  • 适用场景:需保护临界区(Critical Section)代码时。

  • 实现方式

    • 使用 synchronized 关键字修饰方法或代码块。

    • 注意锁的粒度:尽量缩小同步范围以提高性能。

  • 示例

    public class SyncServlet extends HttpServlet {private int counter = 0;private final Object lock = new Object(); // 专用锁对象protected void doGet(HttpServletRequest req, HttpServletResponse resp) {synchronized (lock) { // ✅ 同步代码块counter++;resp.getWriter().write("Sync Count: " + counter);}}
    }

4. 使用 ThreadLocal

  • 适用场景:需要为每个线程维护独立副本的资源(如数据库连接、SimpleDateFormat)。

  • 原理:通过 ThreadLocal 为每个线程创建资源副本,避免竞争。

  • 示例

    public class DateFormatServlet extends HttpServlet {// ✅ 每个线程独立持有 SimpleDateFormatprivate static final ThreadLocal<SimpleDateFormat> dateFormat =ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));protected void doGet(HttpServletRequest req, HttpServletResponse resp) {SimpleDateFormat sdf = dateFormat.get(); // 获取当前线程的副本String date = sdf.format(new Date());resp.getWriter().write(date);}@Overridepublic void destroy() {dateFormat.remove(); // 清理线程副本}
    }

5. 外部化资源管理

  • 适用场景:数据库连接池、缓存等需线程安全的外部资源。

  • 实现方式

    • 使用成熟的线程安全中间件(如 Redis、数据库连接池 HikariCP)。

    • 确保资源本身是线程安全的(如 JDBC 的 DataSource)。


6. Servlet 作用域控制(谨慎使用)

  • 通过配置使 Servlet 非单例(仅特定容器支持,如通过 @WebServlet(urlPatterns="...", loadOnStartup=1, asyncSupported=true) 配置异步模式)。

  • 替代方案:使用框架(如 Spring MVC 的 @Scope("prototype")),但需权衡性能。


关键原则总结

策略适用场景优点缺点
无状态设计绝大多数情况简单高效,无需同步不适合必须共享资源的场景
线程安全类共享计数器、缓存等性能高,无需手动同步功能受限
同步(synchronized)临界区操作(如文件写入)灵活,可控粒度性能下降,可能死锁
ThreadLocal线程绑定资源(如数据库连接)避免竞争,资源隔离内存泄漏风险

常见陷阱与解决方案

  1. SimpleDateFormat 非线程安全

    • ❌ 错误做法:private SimpleDateFormat sdf = new SimpleDateFormat(...);

    • ✅ 正确做法:使用 ThreadLocal 或替换为 DateTimeFormatter(Java 8+ 线程安全)。

  2. Servlet 中存储用户状态

    • ❌ 错误做法:在 Servlet 实例变量中保存用户数据。

    • ✅ 正确做法:使用 HttpSession 或请求参数。

  3. 过度同步导致性能瓶颈

    • ❌ 错误做法:synchronized 修饰整个 service() 方法。

    • ✅ 正确做法:缩小同步范围至必要代码块。


通过合理选择上述策略,可以在保证线程安全的前提下,最大限度提升 Servlet 的并发性能

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

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

相关文章

从Windows到Mac的过渡:学习笔记与心得

作为一名长期使用Windows操作系统的用户&#xff0c;当我决定转换到Mac时&#xff0c;心中充满了期待与好奇。Mac以其独特的操作系统和设计风格著称&#xff0c;虽然有许多相似之处&#xff0c;但仍有不少差异需要适应。为了帮助其他有类似转换需求的朋友&#xff0c;我总结了一…

TestNG接口自动化

第一章、 Rest assured接口测试框架 一、概述 接口自动化的框架&#xff0c;主要是用来做接口自动化测试&#xff0c;返回的报文都是JSON 语法比较简单&#xff0c;只需要掌握常用的方法 用例运行的速度非常快 断言的机制 Json 封装相关方法&#xff0c;jsonpath&#xff0c;x…

【速写】KV-cache与解码的再探讨(以束搜索实现为例)

文章目录 1 Beam Search 解码算法实现2 实现带KV Cache的Beam Search解码3 关于在带kv-cache的情况下的use_cache参数 1 Beam Search 解码算法实现 下面是一个使用PyTorch实现的beam search解码算法&#xff1a; 几个小细节&#xff1a; 束搜索可以加入length_penalty&#…

ABP-Book Store Application中文讲解 - 前期准备 - Part 3:Acme.BookStore项目模块详解之二

1. 汇总 ABP-Book Store Application中文讲解-汇总-CSDN博客 2. 前一章 ABP-Book Store Application中文讲解 - 前期准备 - Part 3:Acme.BookStore项目模块详解 项目之间的引用关系。 目录 1. .Domain.Shared 2. .Domain 3. .Application.Contracts 4. .Application 5…

【Leetcode刷题随笔】349. 两个数组的交集

1. 题目描述 给定两个数组nums1和nums2&#xff0c;返回它们的交集。输出结果中的每个元素一定是唯一的。我们可以不考虑输出结果的顺序。 示例1: 输入:nums1 [1,2,2,1], nums2 [2,2] 输出&#xff1a;[2] 题目条件&#xff1a; 1 < nums1.length, nums2.length < 10…

Unity打包安卓失败 Build failure 解决方法

【Unity】打包安卓失败 Build failure 的解决方法_com.android.build.gradle.internal.res.linkapplicat-CSDN博客 unity在打包时设置手机屏幕横屏竖屏的方法_unity打包默认横屏-CSDN博客

Window、CentOs、Ubuntu 安装 docker

Window 版本 网址&#xff1a;https://www.docker.com/ 下载 下载完成后&#xff0c;双击安装就可以了 Centos 版本 卸载 Docker &#xff08;可选&#xff09; yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-log…

Matlab自学笔记五十四:符号数学工具箱和符号运算、符号求解、绘图

1.什么是符号数学工具箱&#xff1f; 符号数学工具箱是Matlab针对符号对象的运算功能&#xff0c;它引入了一种特殊的数据类型 - 符号对象&#xff1b; 该数据类型包括符号数字&#xff0c;符号变量&#xff0c;符号表达式和符号函数&#xff0c;还包含符号矩阵&#xff0c;以…

OpenCV进阶操作:图像的透视变换

文章目录 前言一、什么是透视变换&#xff1f;二、透视变换的过程三、OpenCV透视变换核心函数四、文档扫描校正&#xff08;代码&#xff09;1、预处理2、定义轮廓点的排序函数3、定义透视变换函数4、读取原图并缩放5、轮廓检测6、绘制最大轮廓7、对最大轮廓进行透视变换8、旋转…

【python】基础知识点100问

以下是Python基础语法知识的30条要点整理,涵盖数据类型、函数、控制结构等核心内容,结合最新资料归纳总结: 基础30问 一、函数特性 函数多返回值 支持用逗号分隔返回多个值,自动打包为元组,接收时可解包到多个变量 def func(): return 1, "a" x, y = func()匿…

采用AI神经网络降噪算法的通信语音降噪(ENC)模组性能测试和应用

采用AI降噪的语言通话环境抑制模组性能效果测试 随着AI时代来临.通话设备的环境噪音抑制也进入AI降噪算法时代. AI神经网络降噪技术是一款革命性的语音处理技术&#xff0c;他突破了传统单麦克风和双麦克风降噪的局限性,利用采集的各种日常环境中的噪音样本进行训练学习.让降噪…

openwrt目录结构(部分)

1&#xff0c;openwrt 原始目录需要注意的目录 tools: 该目录下存放着一些&#xff0c;编译工程的自动化工具包和一些在编译过程用到的命令包&#xff0c; 查看目录下的Makefile&#xff0c;知道其会在编译过程中将依赖包下载 例如&#xff1a; autoconf / lzma / mkimage/ …

RDB和AOF的区别

Redis提供两种主要的持久化机制&#xff1a;RDB&#xff08;Redis Database&#xff09;和AOF&#xff08;Append Only File&#xff09;&#xff0c;它们在数据持久化方式、性能影响及恢复策略上各有特点。以下是两者的对比分析及使用建议&#xff1a; RDB&#xff08;快照持久…

基于大模型的甲状腺结节诊疗全流程预测与方案研究报告

目录 一、引言 1.1 研究背景与目的 1.2 研究意义 1.3 国内外研究现状 二、大模型预测原理与方法 2.1 相关大模型概述 2.2 数据收集与预处理 2.3 模型训练与验证 三、术前预测与评估 3.1 结节性质预测 3.1.1 良恶性判断 3.1.2 与传统诊断方法对比 3.2 手术风险预测…

逆向破解:x64dbg

文章目录 一、CPU窗口1、反汇编窗口2、寄存器窗口3、栈地址窗口4、十六进制数据窗口5、堆栈参数解析窗口 二、常用快捷键三、字符串检索功能四、调试功能1、上一步 一、CPU窗口 1、反汇编窗口 2、寄存器窗口 寄存器窗口用于显示和解释当前线程环境下CPU寄存器的各种状态值和内…

免布线视频桩如何重塑停车管理模式

传统停车管理常因布线复杂、维护成本高而难以推广&#xff0c;而“免布线视频桩”通过无线设计、低功耗与高精度检测&#xff0c;为城市停车提供高效解决方案。作为智慧城市建设的创新工具&#xff0c;免布线视频桩以即装即用、长效续航等特性&#xff0c;正在重塑停车管理模式…

【CTFer成长之路】举足轻重的信息搜集

举足轻重的信息搜集 信息搜集 常见的搜集 题目描述: 一共3部分flag docker-compose.yml version: 3.2services:web:image: registry.cn-hangzhou.aliyuncs.com/n1book/web-information-backk:latestports:- 80:80启动方式 docker-compose up -d 题目Flag n1book{info_…

springboot3+vue3融合项目实战-大事件文章管理系统-更新用户密码

大致分为这三步 首先在usercontroller中增加updatePwd方法 PatchMapping ("/updatePwd")public Result updatePwd(RequestBody Map<String,String> params){//1.校验参数String oldPwd params.get("old_pwd");String newPwd params.get("n…

OpenCV进阶操作:指纹验证、识别

文章目录 前言一、指纹验证1、什么是指纹验证2、流程步骤 二、使用步骤&#xff08;案例&#xff09;三、指纹识别&#xff08;案例&#xff09;1、这是我们要识别的指纹库2、这是待识别的指纹图3、代码4、结果 总结 前言 指纹识别作为生物识别领域的核心技术之一&#xff0c;…

ECLIC中断流程及实际应用 —— RISC-V中断机制(二)

在长期的嵌入式开发实践中&#xff0c;对中断机制的理解始终停留在表面层次&#xff0c;特别当开发者长期局限于纯软件抽象层面时&#xff0c;对中断机制的理解极易陷入"知其然而不知其所以然"的困境&#xff0c;这种认知的局限更为明显&#xff1b;随着工作需要不断…