如何现实servlet的单线程模式

本文探讨了如何使Servlet实现实例与线程一对一的关系,分析了<%@page isThreadSafe=false%>的作用及SingleThreadModel接口在Servlet中的实现原理,并解释为何这种设置在Servlet 2.4中被废弃。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 这个面试题挺经典的,可是网上很多朋友的回答题不达意,所以我在这里就这个问题做一下探讨。

          网上朋友的回答是加入<%@ page isThreadSafe=”false”%>这条命令。天啊,我晕!这是什么命令?是jsp的命令啊,怎么会加入到servlet中呢?当然了,jsp的运行实质是servlet机制,这条命令是jsp页面告诉容器编译“我”的时候实现单线程。那我们看看他编译后的servlet类和以前的servlet有什么不同?没有加入这条指令的页面中servlet类定义是:

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

………………………………//内部实现咱们大可以不看他。
}

而加入这个命令之后的类定义是:

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 SingleThreadModel {

…………………………//同样省略实现细节

}

        我想大家应该很清楚的发现:加入<@page isThreadSafe="false">之后servlet是实现了SingleThreadModel接口的。有兴趣的朋友可以查下相关资料,其实这个接口在servlet2.4之后就废除了。那么为什么废除?实现了这个接口查看代码内容的时候却发现什么方法都没添加,为什么?

       其实这个接口只是一个标识,让容器改变servlet生成策略的。

  默认的,servlet容器是只创建servlet単实例,为请求提供线程池,我们为了能保证servlet的线程安全问题而不在servlet中添加实例属性。

       但是如果一个servlet实现了SingleThreadModel接口那容器在创建实例池,为每个求情分配实例,当用户请求结束时将实例归还实例池。

       这样做真的安全吗?非也!因为每个请求都会分发一个servlet实例,对于同用户下分发的不同的servlet来说很可能用到同一个session中的属性数据,这样当然出现了线程同步的问题,是不安全的!而且不同用户也可能享用同一个context中的数据,也是不安全的。于是在servlet2.4中建议不再使用这样的设置。

  这样一来我们知道:如果非要实现servlet单线程那就要在servlet中实现SingleThreadModel接口,在jsp中添加<@ page isThreadSafe="false">命令。但是这是不被提倡的。

  也有网友疑问:让servlet单线程而多实例本来不是为了线程安全的吗?为什么<@ page isThreadSafe=?>?的答案却是false?

  我觉得这是个误区,这样设置真的是单线程吗?那肯定不是了,其实这个设置只是要容器保证同一时刻只有一个线程能在servlet的service方法中执行,因为默认的容器实例化servlet时时単实例,如果同时只有一个线程去管理这个唯一的servlet实例,那性能将是极其慢的,为了解决这个问题,容器采取了servlet实例池的方式。每个请求一个线程,而一个线程一个servlet。

         因为这种方式并不是线程安全的,所以答案是false。

  终上所述:其实这道题目是指如果让一个servlet实例对应一个线程,而不是一个servlet实例对应多个线程的默认方式。

<think>好的,用户之前已经问过策略模式的详解,现在又询问几大设计模式的详解。我需要先判断用户的需求是什么。可能用户在学习设计模式,已经了解了策略模式,现在想要更全面的了解其他主要的设计模式。 首先,用户可能希望得到一个分类清晰的概述,涵盖创建型、结构型、行为型三大类。需要列举每个类别中的经典模式,并简要说明每个模式的核心思想和应用场景。同时,用户可能希望了解这些模式之间的区别和联系,以及如何选择合适的设计模式。 接下来,我需要确保内容的结构清晰,便于用户理解和记忆。可能需要将每个模式用简短的标题和要点进行解释,避免过于冗长。同时,用户之前的回答中使用了代码示例,因此可以考虑在必要时加入示例,但也要注意不要太多,以免信息过载。 还要考虑用户可能的背景。可能是软件开发人员或学生,正在系统学习设计模式,因此需要准确且专业的解释,同时保持易懂。需要确保每个模式的解释包含定义、结构、应用场景和优点,可能的话提供现实中的例子,如JDK或常见框架中的应用。 另外,用户可能希望了解设计模式之间的关系,比如哪些模式经常一起使用,或者它们的对比。例如,策略模式和状态模式的区别,或者工厂方法和抽象工厂的不同。因此,在回答中可以加入对比表格或说明,帮助用户区分相似的模式。 最后,需要检查是否有遗漏的重要设计模式,确保覆盖GoF的23种设计模式中的主要几种,但不需要全部详细说明,而是挑选最常用和重要的进行详解。同时,要避免使用过于技术化的术语,或者在必要时进行解释,确保内容的可读性。 总结下来,回答的结构应该是先分类,然后在每个类别下列举模式,每个模式有定义、结构、应用场景、示例和优点。可能的话,加入对比和实际应用案例,帮助用户更好地理解和应用这些设计模式。</think>以下是软件工程中最核心的**23种设计模式**的系统分类与详解(按类型分组说明): --- ### 一、创建型模式(5种) #### 1. 工厂方法模式(Factory Method) - **定义**:通过$工厂接口$创建对象,子类决定实例化的具体类 - **结构**: ```java interface Product {} class ConcreteProduct implements Product {} interface Factory { Product create(); } class ConcreteFactory implements Factory { public Product create() { return new ConcreteProduct(); } } ``` - **场景**:数据库连接器、日志记录器 - **优点**:解耦客户端与具体产品 #### 2. 抽象工厂模式(Abstract Factory) - **定义**:创建$相关对象族$的接口,无需指定具体类 - **对比**: | | 工厂方法 | 抽象工厂 | |----------|------------------------|------------------------| | 产品维度 | 单一产品 | 产品族 | | 扩展方式 | 新增工厂子类 | 需要修改工厂接口 | | 复杂度 | 低 | 高 | #### 3. 建造者模式(Builder) - **核心**:分步构建复杂对象,例如: ```java new Computer.Builder() .setCPU("i7").setRAM(32GB) // 链式调用 .build(); ``` - **应用**:JSON解析器、文档生成器 #### 4. 原型模式(Prototype) - **实现**:通过$clone()$复制已有对象 - **优势**:比直接new对象更高效(特别是初始化成本高时) #### 5. 单例模式(Singleton) - **关键代码**: ```java public class Singleton { private static volatile Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized(Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } } ``` - **注意**:多线程安全与反序列化问题 --- ### 二、结构型模式(7种) #### 1. 适配器模式(Adapter) - **类比**:电源转接头 - **类型**: - 类适配器:继承被适配类(Java不支持多继承) - 对象适配器:组合被适配对象(推荐) #### 2. 桥接模式(Bridge) - **公式**:$抽象部分 \rightarrow 实现部分$ ```java abstract class Shape { // 抽象 protected Color color; // 实现 public Shape(Color c) { this.color = c; } abstract void draw(); } ``` #### 3. 组合模式(Composite) - **树形结构**:统一处理叶子节点和组合节点 ```text Component / \ Leaf Composite / \ Leaf Composite ``` #### 4. 装饰器模式(Decorator) - **JDK案例**:Java I/O流体系 ```java InputStream in = new BufferedInputStream( new FileInputStream("test.txt")); ``` #### 5. 外观模式(Facade) - **本质**:为子系统提供统一入口 - **场景**:电商下单流程(库存、支付、物流的整合接口) #### 6. 享元模式(Flyweight) - **内存优化**:共享细粒度对象(如棋子的颜色属性) - **状态分类**: - 内部状态:共享不变的部分(如字符样式) - 外部状态:变化的部分由客户端维护(如字符位置) #### 7. 代理模式(Proxy) - **类型对比**: | 代理类型 | 特点 | 示例 | |------------|-------------------------------|---------------------| | 静态代理 | 手动编写代理类 | 常规代理 | | 动态代理 | 运行时生成(JDK/CGLIB) | Spring AOP | | 虚拟代理 | 延迟加载大对象 | 图片预加载 | --- ### 三、行为型模式(11种) #### 1. 责任链模式(Chain of Responsibility) - **处理流程**: ```text Request → HandlerA → HandlerB → HandlerC (任一处理成功则终止传递) ``` - **应用**:Servlet过滤器、审批流程 #### 2. 命令模式(Command) - **组成**: ```text Invoker(调用者) → Command(命令) → Receiver(执行者) ``` - **扩展**:支持撤销操作、宏命令 #### 3. 解释器模式(Interpreter) - **领域**:特定语法解析,如SQL解析、正则表达式 #### 4. 迭代器模式(Iterator) - **分离**:集合遍历与集合实现的解耦 - **JDK实现**:`java.util.Iterator` #### 5. 中介者模式(Mediator) - **通信架构**: ```text 组件A → 中介者 ← 组件B 代替直接网状通信 ``` - **案例**:GUI组件交互(如对话框控件协调) #### 6. 备忘录模式(Memento) - **三要素**: - Originator:创建备忘录 - Memento:存储状态 - Caretaker:管理备忘录历史 #### 7. 观察者模式(Observer) - **推/拉模型**: ```java // 推模型 void update(Observable o, Object arg); // 拉模型(需主动获取状态) void update(Observable o); ``` - **JDK实现**:`java.util.Observable` #### 8. 状态模式(State) - **对比策略模式**: | | 策略模式 | 状态模式 | |--------------|------------------------------|------------------------------| | 切换主动性 | 客户端控制 | 状态自动转换 | | 目标 | 不同算法实现 | 状态驱动的行为变化 | #### 9. 模板方法模式(Template Method) - **钩子方法**:通过$protected$方法控制流程扩展点 ```java abstract class Game { abstract void initialize(); // 必须实现 protected void addHook() {} // 可选钩子 final void play() { // 模板方法 initialize(); addHook(); start(); } } ``` #### 10. 访问者模式(Visitor) - **双分派技术**:在元素类中调用访问者的方法 ```java interface Element { void accept(Visitor v); } class ConcreteElement implements Element { public void accept(Visitor v) { v.visit(this); // 第二次分派 } } ``` #### 11. 策略模式(已单独详解) --- ### 四、模式选择指南 1. **创建问题** - 需要控制实例 → 工厂/单例 - 复杂对象构建 → 建造者 - 克隆对象 → 原型 2. **结构问题** - 接口转换 → 适配器 - 动态添加功能 → 装饰器 - 树形结构 → 组合 3. **行为问题** - 算法切换 → 策略 - 状态变化 → 状态 - 事件通知 → 观察者 --- ### 五、设计原则总结 1. **SOLID原则** - **SRP**(单职责原则) → 状态/策略模式 - **OCP**(开闭原则) → 装饰器/观察者模式 - **LSP**(里氏替换) → 所有继承体系 - **ISP**(接口隔离) → 适配器模式 - **DIP**(依赖倒置) → 工厂方法模式 2. **组合优于继承** → 桥接/策略模式 --- 掌握这些设计模式的核心在于理解其**适用场景**而非机械套用,建议通过实际项目中的重构来加深体会。每个模式都是特定问题的经典解决方案,但过度使用会导致系统复杂度上升,需在灵活性与简洁性之间取得平衡。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值