Servlet:单实例多线程,也可以认为是单进程多线程的运行在容器中。线程不安全,因为被多个线程访问一个实例,共享的数据可能会发生安全问题。
每个客户端访问Servlet时,都是一个独立的线程。
概述
在探讨java线程安全前,让我们先简要介绍一下Java语言。
任何语言,如C++,C#,Java,它们都有相通之处,特别是语法,但如果有人问你,Java语言的核心是什么?类库?关键字?语法?似乎都不是。Java语言的核心,也就是Sun始终不愿意开源的东西:Java虚拟机的实现(不过sun公开了其Java虚拟机规范),也就有了BEA的JRockit,IBM的Jikes,Sun的Hotspot。
Java的核心有两点,Java类加载(Java Class Loader)和Java内存管理,它们具体体现在Java类库的以下几个类:
java.lang.ClassLoader(java.lang.Class):我们调用的类,包括其接口和超类,import的类是怎么被Java虚拟机载入的?为什么static的字段在servlet容器里面可以一直生存下去(Spring容器中)?
java.lang.Thread(java.lang.ThreadLocal):垃圾回收是怎么进行的(垃圾回收线程)?我们的程序是怎么退出的?
java.lang.refelect.Proxy(java.lang.refelect.Method):为什么Tomcat、Tapestry、Webwork、Spring等容器和框架可以通过配置文件来调用我们写的类?Servlet规范、JSF规范、EJB规范、JDBC规范究竟是怎么回事?为什么它们几乎都是一些接口,而不是具体类?
Servlet线程安全
在Java的server side开发过程中,线程安全(Thread Safe)是一个尤为突出的问题。因为容器,如Servlet、EJB等一般都是多线程运行的。虽然在开发过程中,我们一般不考虑这些问题,但诊断问题(Robust),程序优化(Performance),我们必须深入它们。
什么是线程安全?
在Java里,线程安全一般体现在两个方面:
1、多个thread对同一个java实例的访问(read和modify)不会相互干扰,它主要体现在关键字synchronized。如ArrayList和Vector,HashMap和Hashtable(后者每个方法前都有synchronized关键字)。如果你在interator一个List对象时,其它线程remove一个element,问题就出现了。
2、每个线程都有自己的字段,而不会在多个线程之间共享。它主要体现在java.lang.ThreadLocal类,而没有Java关键字支持,如像static、transient那样。
一个普遍的疑问,我们的Servlet中能够像JavaBean那样declare instance或static字段吗?如果不可以?会引发什么问题?
答案是:不可以。
解决之道:
1. 实现 SingleThreadModel 接口,该接口指定了系统如何处理对同一个Servlet的调用。如果一个Servlet被这个接口指定,那么在这个Servlet中的service方法将不会有两个线程被同时执行,当然也就不存在线程安全的问题。这种方法只要继承这个接口就行了
public class DemoServerlet extends HttpServlet implements SingleThreadModel {
…………
}
2. 同步对共享数据的操作
使用synchronized 关键字能保证一次只有一个线程可以访问被保护的区段,在本论文中的Servlet可以通过同步块操作来保证线程的安全。同步后的代码如下:
Public class DemoServerlet extends HttpServlet {
…………
synchronized (this){XXXX}
}
3. 避免使用实例变量
线程安全问题还有些是由实例变量造成的,只要在Servlet里面的任何方法里面都不使用实例变量,那么该Servlet就是线程安全的。
Servlet的多线程机制
Servlet体系结构是建立在Java多线程机制之上的,它的生命周期是由Web容器负责的。当客户端第一次请求某个Servlet时,Servlet容器将会根据web.xml配置文件实例化这个Servlet类。当有新的客户端请求该Servlet时,一般不会再实例化该Servlet类,也就是有多个线程在使用这个实例。Servlet容器会自动使用线程池等技术来支持系统的运行,如图1所示。
Java的内存模型JMM(Java Memory Model)JMM 主要是为了规定了线程和内存之间的一些关系。根据JMM的设计,系统存在一个主内存(Main Memory),Java中所有实例变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory),工作内存由缓存和堆栈两部分组成,缓存中保存的是主存中变量的拷贝,缓存可能并不总和主存同步,也就是缓存中变量的修改可能没有立刻写到主存中;堆栈中保存的是线程的局部变量,线程之间无法相互直接访问堆栈中的变量。根据JMM,我们可以将论文中所讨论的Servlet实例的内存模型抽象为图3所示的模型。
从Java 内存模型也可以知道,方法中的临时变量是在栈上分配空间,而且每个线程都有自己私有的栈空间,所以它们不会影响线程的安全。
Servlet的线程安全问题只有在大量的并发访问时才会显现出来,并且很难发现,因此在编写Servlet程序时要特别注意。线程安全问题主要是由实例变量造成的,因此在Servlet中应避免使用实例变量。如果应用程序设计无法避免使用实例变量,那么使用同步来保护要使用的实例变量,但为保证系统的最佳性能,应该同步可用性最小的代码路径。
同时因为struts也是通过servlet来实现的,因为Struts的Action被设计为线程不安全的,所以也涉及到这个问题,所以也使用同样的方法来解决!
相关推荐
此外,Servlet中的一些难点问题,比如线程安全、性能优化、异步处理等,也是开发者需要关注的。理解和掌握Servlet容器的工作原理,有助于开发人员更好地设计和优化Web应用,提高系统的稳定性和性能。 总的来说,...
Servlet容器还负责线程安全,通常一个Servlet实例可能会服务于多个并发请求,通过线程池来提高性能。 对于最新的Servlet API,其类层次结构更加丰富和优化,提供了更多高级功能,如异步处理、过滤器等。这些API使得...
4. **多线程模型**:Servlet是线程安全的,这意味着每个请求都会创建一个新的线程来调用Servlet实例。 5. **Servlet容器**:Servlet运行在Servlet容器中,负责管理Servlet的生命周期,例如Tomcat。 **Tomcat** ...
### 深入Java Web心脏:Servlet工作原理全解析 #### Java语言概述 Java作为一种流行的编程语言,由Sun Microsystems(现归Oracle所有)于1995年首次发布。其设计初衷是为了满足跨平台性、面向对象编程、健壮性、...
在Java Web开发中,Struts框架是一个非常流行的MVC(模型-视图-控制器)架构。然而,使用Struts框架时,开发者需要注意一个关键...在设计和编写Action类时,应始终考虑其线程安全性,以确保应用程序的正确性和稳定性。
由于Servlet实例默认是多线程的,因此在编写Servlet时需要注意线程安全问题。例如,避免在Servlet实例中使用非线程安全的全局变量。 7. **Servlet的异步处理**: 自Java Servlet 3.0版本开始,Servlet支持异步...
通过对jakarta-servletapi-4-src.zip源码的分析,开发者不仅可以加深对Servlet API的理解,还能学习到如何优化Web应用程序的性能、安全性以及用户体验。这是一次深入挖掘Java Web核心技术的宝贵机会,对于任何希望...
在这篇文章中,我们将详细介绍 Servlet 的使用实例解析,包括 Servlet 的创建、生命周期、线程安全性、使用方法等方面的知识点。 Servlet 的创建 Servlet 的创建有三种方式:实现 javax.servlet.Servlet 接口、...
8. **Servlet的线程安全问题?** Servlet默认是多线程的,所以必须谨慎处理共享数据,避免线程安全问题。通常通过使用synchronized关键字或ThreadLocal来实现线程隔离。 9. **Tomcat如何处理并发请求?** Tomcat...
此外,容器还会处理Servlet的线程安全问题,因为多个请求可能会并发地访问同一个Servlet实例。 5. **会话管理**:Servlet容器还负责维护客户端的会话状态,通过Session对象实现。当用户首次访问Web应用时,容器会...
1. **线程安全**:由于Servlet默认是多线程的,开发者需要注意同步问题,避免在Servlet中使用全局变量或不线程安全的对象。 2. **性能优化**:可以通过实现`SingleThreadModel`接口使每个请求都创建新的Servlet实例...
为了提高代码的可维护性和安全性,可以使用预编译的PreparedStatement来防止SQL注入。 **图灵机器人**: 图灵机器人是一种智能对话系统,可以在服务端集成,使Web应用具有聊天功能。Servlet可以通过发送HTTP请求到...
- **与Java Servlet 2.3规范的兼容性**:Servlet 2.4在2.3的基础上进行了一些改进和增强,如增加了`HttpSessionListener.sessionDestroyed`方法,以及`ServletRequest`中的新方法。 2. **Servlet接口** - **请求...
为了提高性能,Servlet容器会使用线程池来并发处理请求,因此Servlet必须是线程安全的。避免使用类级别的变量存储状态,而是使用实例变量或会话对象。同时,使用同步块或锁来保护共享资源是保证多线程环境下正确性的...
此外,Oracle还提供了数据库集群、数据仓库、安全性和性能优化等特性,以满足大规模业务需求。 【Servlet】 Servlet是Java EE的一部分,它是一种服务器端的Java小程序,用于扩展Web服务器的功能。Servlet可以处理...
**Servlet3源码解析** Servlet技术是Java Web开发中的核心组件,它允许开发者编写服务器端程序来处理HTTP请求。Servlet3.0是Servlet规范的一个重要版本,引入了许多新特性和改进,大大提升了开发效率和应用的灵活性...
因此,为了确保聊天的实时性,开发者需要考虑线程安全问题,避免出现数据竞争和死锁的情况。可能的做法包括使用同步机制,如`synchronized`关键字,或者使用线程安全的数据结构。 此外,服务器端还需要维护一个用户...
8. **安全增强**:添加了新的安全相关API,如`HttpServletRequest.isUserInRole()`和`HttpServletRequest.getRemoteUser()`,以及对基本认证和摘要认证的支持,增强了Web应用的安全性。 9. **生命周期管理**:...
Servlet容器提供了Servlet运行的环境,同时管理了Servlet的生命周期和线程安全等问题。 2. Servlet与Servlet容器 Servlet容器(例如Tomcat, Jetty等)负责管理Servlet的生命周期,包括初始化、请求处理、以及销毁等...
1. Servlet API:提供了一个标准的 API,保证了程序开发的一致性 2. Servlet 容器:提供了一个运行环境,用于部署和管理 Servlet 3. Servlet 工具:提供了一些工具,用于开发、测试和调试 Servlet 在 Java 服务器...