Servlet不是线程安全的。

要解释为什么Servlet为什么不是线程安全的,需要了解Servlet容器(即Tomcat)使如何响应HTTP请求的。

当Tomcat接收到Client的HTTP请求时,Tomcat从线程池中取出一个线程,之后找到该请求对应的Servlet对象并进行初始化,之后调用service()方法。要注意的是每一个Servlet对象再Tomcat容器中只有一个实例对象,即是单例模式。如果多个HTTP请求请求的是同一个Servlet,那么着两个HTTP请求对应的线程将并发调用Servlet的service()方法。

上图中的Thread1和Thread2调用了同一个Servlet1,所以此时如果Servlet1中定义了实例变量或静态变量,那么可能会发生线程安全问题(因为所有的线程都可能使用这些变量)。

比如下面的Servlet中的 name 和 i变量就会引发线程安全问题。

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.text.SimpleDateFormat;

import java.util.Date;

public class ThreadSafeServlet extends HttpServlet {

public static String name = "Hello"; //静态变量,可能发生线程安全问题

int i; //实例变量,可能发生线程安全问题

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

@Override

public void init() throws ServletException {

super.init();

System.out.println("Servlet初始化");

}

@Override

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

System.out.printf("%s:%s[%s]\n", Thread.currentThread().getName(), i, format.format(new Date()));

i++;

try {

Thread.sleep(5000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.printf("%s:%s[%s]\n", Thread.currentThread().getName(), i, format.format(new Date()));

resp.getWriter().println("

" + i + "

");

}

}

在Tomcat中启动这个Servlet并在浏览器发起多个HTTP访问,最后会发现变量 i 是多线程共享的。

如果需要更加深入透彻地了解Tomcat接收HTTP的细节,以及与Servlet交互的细节,可以深入看看Tomcat的架构和源码。

参考资料

java中的servlet是线程安全的嘛_Java面试题:Servlet是线程安全的吗?(转)相关推荐

  1. 在java中重写方法应遵循规则的包括_Java面试题集合篇二

    Java面试题之Java集合篇二1.遍历一个List有哪些不同的方式? List<String> strList = new ArrayList<>(); //使用for-ea ...

  2. 以下对java中的接口的描述错误的是_Java笔试题

    所有内容都是在网上查找的 1.下面哪些是Thread类的方法? A.Start() B.run()方法 C.exit()方法 D. getPriority()方法 解析:exit()方法 是 Syst ...

  3. java线程池拒绝策略_Java核心知识 多线程并发 线程池原理(二十三)

    线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线程创建后 启动这些任务,如果线程数量超过了最大数量超出数量的线程排队等候,等其它线程执行完毕, 再从队列中取出任务来执行.他 ...

  4. 集合类 Java中的集合类解析和一些有深入的面试题

    Java集合类解析 List.Map.Set三个接口,存取元素时,各有什么特点? List 以特定次序来持有元素,可有重复元素.Set 无法拥有重复元素,内部排序.Map 保存key-value值,v ...

  5. java中三种可能导致异常的情况_JAVA基础知识点之异常

    一.JAVA异常 异常指不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等.异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程.Java通 过API中Throwable类的众多子类描 ...

  6. java中栈和堆都存哪些东西_java中栈内存与堆内存(JVM内存模型)

    java中栈内存与堆内存(JVM内存模型) Java中堆内存和栈内存详解1 和 Java中堆内存和栈内存详解2 都粗略讲解了栈内存和堆内存的区别,以及代码中哪些变量存储在堆中.哪些存储在栈中.内存中的 ...

  7. Java 中IO流详解(附实例代码/面试题)

    Java I/O流详解 前言 一.I/O流是什么? 二.IO流分类: 1. 流程图: io流对象 2. io流的优缺点: 3. io 流Java中用途有哪些? 三.一些 io 实例 四.面试题: 前言 ...

  8. java中的成员变量和局部变量的区别_java中成员变量与局部变量区别分析

    本文实例分析了java中成员变量与局部变量区别.分享给大家供大家参考.具体分析如下: 成员变量:在这个类里定义的私有变量,属于这个类. 创建以及使用成员变量 public class Person { ...

  9. java中static类的作用是什么意思_java中static关键字是什么意思

    java中static关键字是什么意思 发布时间:2020-11-11 11:01:11 来源:亿速云 阅读:86 作者:小新 这篇文章给大家分享的是有关java中static关键字是什么意思的内容. ...

最新文章

  1. 2021年大数据Spark(二十三):SparkSQL 概述
  2. 如何让我们的vmware虚拟机上网!!
  3. linux find 多路径,linux多路径几个比较有用的命令
  4. python与鸭子类型
  5. P13 最优控制系统-《Matlab/Simulink与控制系统仿真》程序指令总结
  6. 中国移动研究院2020春招技术综合JAVA在线编程题第二题
  7. C++生成指定范围内的随机数
  8. Java集合:Collection接口
  9. python学习之老男孩python全栈第九期_day017作业
  10. html页面怎么添加打印,在网页中添加打印按钮或链接的方法
  11. nmon--linux压力测试工具
  12. Fragment学习笔记
  13. 蓝牙 配对 android,Android蓝牙工具类:连接、配对、传输
  14. 开始学习docker
  15. NUDT硕士论文LaTeX模板
  16. 网易云通信 java 登录_Java接入网易云信工具类
  17. Lavas的简单入门
  18. SVM支持向量机原理及核函数
  19. 安装和使用openBMC官网维护的qemu
  20. 双色F3.75LED点阵屏中保护电路74HC04的作用

热门文章

  1. Spring MVC -- 国际化
  2. pyinstaller打包pyqt文件(转)
  3. 10.19 qbxt国庆day3
  4. XHProf报告字段含义
  5. 在CDS(Core Data Services)中使用DCL(Data Control Language)
  6. Object类—复写equals方法,hashCode方法,toString方法
  7. C# 获取并判断操作系统版本,解决Win10、 Windows Server 2012 R2 读取失败的方案
  8. String.split()方法你可能不知道的一面
  9. 【AS3代码】添加/删除XML子元素及属性
  10. 【JUnit 报错】 method initializationerror not found:JUnit4单元测试报错问题