`
荷戟者
  • 浏览: 280244 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

有状态,无状态对象是什么概念

 
阅读更多

转自:http://www.iteye.com/topic/960532

 

 

基本概念: 

有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象 ,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。

无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象 .不能保存数据,是不变类,是线程安全的。

代码更好理解:

Java代码
  1.   
  2. public   class  StatefulBean {   
  3.   
  4.      public   int  state;   
  5.      // 由于多线程环境下,user是引用对象,是非线程安全的   
  6.      public  User user;   
  7.   
  8.      public   int  getState() {   
  9.          return  state;   
  10.     }   
  11.   
  12.      public   void  setState( int  state) {   
  13.          this .state = state;   
  14.     }   
  15.   
  16.      public  User getUser() {   
  17.          return  user;   
  18.     }   
  19.   
  20.      public   void  setUser(User user) {   
  21.          this .user = user;   
  22.     }   
  23. }   
  24.   
  25.   
  26. public   class  StatelessBeanService {   
  27.   
  28.      // 虽然有billDao属性,但billDao是没有状态信息的,是Stateless Bean.   
  29.     BillDao billDao;   
  30.   
  31.      public  BillDao getBillDao() {   
  32.          return  billDao;   
  33.     }   
  34.   
  35.      public   void  setBillDao(BillDao billDao) {   
  36.          this .billDao = billDao;   
  37.     }   
  38.   
  39.      public  List<User> findUser(String Id) {   
  40. return   null ;   
  41.     }   
  42. }  


单例模式中的有状态和无状态: 
单例类可以是有状态的(stateful),一个有状态的单例对象一般也是可变(mutable)单例对象 。 有状态的可变的单例对象常常当做状态库(repositary)使用。比如一个单例对象TaskCache(Spring中配为singleton)可以 持有一个AtomicLong类型的属性,用来给一个系统提供一个数值惟一的序列号码,作为任务通迅管理的ID生成器。同时,一个单例类也可以持有一个聚 集,从而允许存储多个状态,如示例中的ExpiringMap缓存任务列表。
代码示例:

Java代码
  1. import  java.util.concurrent.atomic.AtomicLong;   
  2.   
  3. import  org.apache.mina.util.ExpiringMap;   
  4.   
  5.   
  6. public   class  TaskCache {   
  7.   
  8.      // 请求超时   
  9.      private   short  requestTimeout;   
  10.   
  11.      // 这个缓存Map是线程安全,并且有定时超时功能   
  12.      private  ExpiringMap<String, Object> tasksMap =  new  ExpiringMap<String, Object>();   
  13.   
  14.      // 线程安全的原子类,示例有状态的单例类   
  15.      private   static  AtomicLong seqNo =  new  AtomicLong( 1 );   
  16.   
  17.      // 示例有状态的单例类   
  18.      public  Long nextSeqNo() {   
  19.          return  seqNo.getAndIncrement();   
  20.     }   
  21.   
  22.      public   void  setRequestTimeout( short  requestTimeout) {   
  23.          this .requestTimeout = requestTimeout;   
  24.     }   
  25.   
  26.      // 启动过期检测   
  27.      public   void  startExpiring() {   
  28.         tasksMap.getExpirer().setTimeToLive(requestTimeout);   
  29.         tasksMap.getExpirer().startExpiringIfNotStarted();   
  30.     }   
  31.   
  32.      // 停止过期检测   
  33.      public   void  stopExpiring() {   
  34.         tasksMap.getExpirer().stopExpiring();   
  35.     }   
  36.   
  37.      // 取任务列表.   
  38.      public  Object getTasks(String key) {   
  39.          return  tasksMap.get(key);   
  40.     }   
  41.   
  42.      // 去除任务列表.   
  43.      public  Object removeTasks(String key) {   
  44.          return  tasksMap.remove(key);   
  45.     }   
  46.   
  47.      // 添加任务列表.   
  48.      public   void  addTasks(String key, Object value) {   
  49.         tasksMap.put(key, value);   
  50.     }   
  51. }  



单例类也可以是没有状态的(stateless) ,仅用做提供工具性函数的对象。既然是为了提供工具性函数,也就没有必要创建多个实例,因此使用单例模式很合适。平常的单例类都是没有状态的,这里就不示例了。一个没有状态的单例类也就是不变(Immutable)单例类。关于不变模式,请参考 http://www.javaeye.com/topic/959751 

EJB中的有状态与无状态: 

1.Stateful session bean的每个用户都有自己的一个实例,所以两者对stateful session bean的操作不会影响对方。另外注意:如果后面需要操作某个用户的实例,你必须在客户端缓存Bean的Stub对象(JSP通常的做法是用Session缓存),这样在后面每次调用中,容器才知道要提供相同的bean实例。

2.Stateless Session Bean不负责记录使用者状态,Stateless Session Bean一旦实例化就被加进会话池中,各个用户都可以共用。如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响。

3.从内存方面来看,Stateful Session Bean与Stateless Session Bean比较,Stateful Session Bean会消耗J2EE Server 较多的内存,然而Stateful Session Bean的优势却在于他可以维持使用者的状态。

Spring中的有状态(Stateful)和无状态(Stateless) 

1.通过上面的分析,相信大家已经对有状态和无状态有了一定的理解。无状态的Bean适合用不变模式,技术就是单例模式,这样可以共享实例,提高性能。有状态的Bean,多线程环境下不安全,那么适合用Prototype原型模式。Prototype: 每次对bean的请求都会创建一个新的bean实例。

2.默认情况下,从Spring bean工厂所取得的实例为singleton(scope属性为singleton),容器只存在一个共享的bean实例。

3.理解了两者的关系,那么scope选择的原则就很容易了:有状态的bean都使用prototype作用域,而对无状态的bean则应该使用singleton作用域。

4.如Service层、Dao层用默认singleton就行,虽然Service类也有dao这样的属性,但dao这些类都是没有状态信息的,也就是 相当于不变(immutable)类,所以不影响。Struts2中的Action因为会有User、BizEntity这样的实例对象,是有状态信息 的,在多线程环境下是不安全的,所以Struts2默认的实现是Prototype模式。在Spring中,Struts2的Action中,scope 要配成prototype作用域。

Servlet、Struts中的有状态和无状态: 

1.Servlet体系结构是建立在Java多线程机制之上的,它的生命周期是由Web 容器负责的。一个Servlet类在Application中只有一个实例存在,也就是有多个线程在使用这个实例。这是单例模式的应用。无状态的单例是线 程安全的,但我们如果在Servlet里用了实例变量,那么就变成有状态了,是非线程安全的。如下面的用法就是不安全的,因为user,out都是有状态 信息的。

Java代码
  1.   
  2. public   class  UnSafeServlet HttpServlet{   
  3.        
  4.     User user;   
  5.     PrintWriter out;   
  6.        
  7.      public   void  doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{   
  8.          //do something...   
  9.     }   
  10. }  


Out,Request,Response,Session,Config,Page,PageContext是线程安全的,Application在整个系统内被使用,所以不是线程安全的.

2.Struts1也是基于单例模式实现,也就是只有一个Action实例供多线程使用。默认的模式是前台页面数据通过actionForm传入,在 action中的excute方法接收,这样action是无状态的,所以一般情况下Strunts1是线程安全的。如果Action中用了实例变量,那 么就变成有状态了,同样是非线程安全的。像下面这样就是线程不安全的。

Java代码
  1.   
  2. public   class  UnSafeAction1  extends  Action {   
  3.   
  4.      // 因为Struts1是单例实现,有状态情况下,对象引用是非线程安全的   
  5.     User user;   
  6.   
  7.      public   void  execute() {   
  8.          // do something...   
  9.     }   
  10.   
  11.      public  User getUser() {   
  12.          return  user;   
  13.     }   
  14.   
  15.      public   void  setUser(User user) {   
  16.          this .user = user;   
  17.     }   
  18. }    



3.Struts2默认的实现是Prototype模式。也就是每个请求都新生成一个Action实例,所以不存在线程安全问题。需要注意的是,如果由Spring管理action的生命周期, scope要配成prototype作用域。

4.如何解决Servlet和Struts1的线程安全问题,当我们能比较好的理解有状态和无状态的原理,自然很容易得出结论:不要使用有状态的bean,也就是不要用实例变量 。如果用,就要用prototype模式。Struts1 user guide里有: Only Use Local Variables - The most important principle that aids in thread-safe coding is to use only local variables, not instance variables , in your Action class.

总结: 
Stateless无状态用单例Singleton模式,Stateful有状态就用原型Prototype模式。 
Stateful 有状态是多线程编码的天敌,所以在开发中尽量用Stateless无状态,无状态是不变(immutable)模式的应用,有很多优点:不用管线程和同步的问题 ,如果值是不可变的,程序不用担心多个线程改变共享状态,所以可以避免线程竞争的bugs. 因为没有竞争,就不用用locks等机制,所以无状态的不变机制,也可以避免产生死锁现象。

国外一些哥们的观点: 
Immutable objects may not be altered after their creation. So: Yes, they are some kind of stateless.As immutable objects can not be changed, there is no need for locking - reading access to objects is always threadsafe (when not modifying variables). Therefore, real immutable objects are always threadsafe.

Rod Johnson大叔的观点: 
Stateless or Stateful?
Service objects will usually be stateless. Stateless service layers are highly scalable: They pose no replication issues and there is no need to allocate additional resources for every client. (Remember that one of
the key motivations of a middle tier is to share resources between multiple clients.) It is also much easier for stateless service layers to support remote clients, if necessary. A stateless service layer is one concession of object orientation that I find not too painful.
此处省去N个字。
If possible, design applications to use a stateless service layer. Hold state in the web tier, rather than in the business logic tier, if possible.

 

转自:http://www.iteye.com/topic/960532

分享到:
评论

相关推荐

    域对象在持久化层的状态

    本文将围绕“域对象在持久化层的状态”这一主题,深入探讨其核心概念、作用机制以及关键操作点,帮助读者构建更为扎实的持久化层知识体系。 #### 一、域对象的三种状态 域对象,通常指业务逻辑中的实体类,它们在...

    关于有状态和无状态会话bean的解释

    本篇文章将深入探讨有状态(Stateful)和无状态(Stateless)会话Bean的区别,以及如何在实际应用中选择合适的类型。 首先,我们要理解会话Bean的基本概念。会话Bean是一种服务器端对象,它作为客户端应用程序与...

    JPA学习笔记-EJB-05JPA实体对象状态和实体对象的高级操作

    实体对象的状态管理和实体监听器的使用是JPA中非常重要的概念。通过理解和应用这些概念,开发者可以更好地控制数据的持久化过程,并实现高效、可靠的应用程序开发。无论是从数据同步的角度考虑,还是从日志记录的...

    常用对象和状态管理的一些例子

    在IT行业中,尤其是在前端开发领域,对象和状态管理是至关重要的概念。对象是JavaScript等编程语言中的...对于初学者来说,从简单的对象操作开始,逐步学习状态管理的概念,将有助于他们更好地应对实际项目中的挑战。

    PB编写的状态栏用户对象

    通过以上分析,我们可以了解到这个状态栏用户对象的创建和使用过程涉及了PowerBuilder的对象封装、用户对象的定义和实现、以及对象的使用和初始化等概念。开发者通过封装状态栏的功能,简化了状态栏的集成过程,提高...

    SSHnote session函数的对象状态转换

    SSHnote session函数的对象状态转换是Hibernate框架中一个关键的概念,涉及到如何管理数据库中的持久化对象。在Hibernate中,对象有三种基本状态:瞬时(Transient)、持久化(Persistent)和脱管(Detached)。理解...

    图书管理系统-状态图

    入口动作是对象进入状态时执行的动作,出口动作则是对象退出状态时执行的动作,内部转换发生在对象处于同一状态下但需要反映内部事件或条件变化时,延迟事件指的是在当前状态下可以推迟处理的事件,而子状态则描述了...

    Java入门:状态对象--数据库的替代者

    这涉及到一种概念,即“状态对象”(State Object),它被视为数据库的潜在替代方案之一,在某些场景下能够提供更为高效和灵活的状态管理方式。 #### 什么是状态对象? 状态对象,简单来说,是在内存中存储和管理...

    一种基于分支条件的对象状态机自动提取方法

    #### 二、对象状态机的概念与重要性 **对象状态机(Object State Machine, OSM)**是一种用于描述面向对象系统中单个对象在其生命周期内状态变化及相应行为的模型。它不仅可以清晰地表示出对象的状态变迁过程,还...

    Python-一个轻量级面向对象的Python有限状态机实现

    在软件工程中,有限状态机(Finite State Machine, FSM)是一个重要的概念,它用于建模系统的行为,通过一系列预定义的状态和转换来描述系统的动态过程。在Python中,有多种库可以帮助我们创建有限状态机,其中之一...

    C#面向对象设计模式纵横谈(22):(行为型模式) State 状态模式

    状态模式的核心概念是状态对象,每个状态对象代表系统的一种特定状态,并封装了该状态下对象的行为。状态模式通过将状态对象引入到系统中,将对象的行为委托给当前状态对象来执行,从而解耦了对象本身与具体状态之间...

    事件型状态机,状态机概念,LabView

    状态机的概念源于计算机科学,它是一种描述对象行为的模型,通过定义不同状态以及状态之间的转换来实现系统的逻辑控制。 事件型状态机的核心是事件,每个事件都可能触发状态的转移。在LabVIEW中,这种状态机通常...

    Hibernate对象持久化状态

    在 Hibernate 框架中,Java 对象的状态管理和 Session 缓存是核心概念,它们直接影响着数据的持久化过程和数据库交互效率。本篇文章将详细阐述 Hibernate 中对象的三种状态——临时状态、持久化状态和游离状态,以及...

    面向对象技术 ATM类的状态图 面向对象建模技术

    在本主题中,我们将深入探讨面向对象技术,特别是通过ATM(自动取款机)类的状态图来阐述面向对象建模技术。 首先,让我们了解面向对象的基本概念。面向对象编程(Object-Oriented Programming,OOP)是一种编程...

    c语言状态机资料-unlocked_面向对象分析_行为继承_状态机_

    本资料主要探讨了状态机的基础理论,并深入讲解如何将面向对象分析和行为继承的概念应用于状态机的设计与实现。 首先,理解状态机的基础概念至关重要。状态机是一种数学模型,用来描述一个系统或对象随时间变化的...

    无状态聊天(ajax)

    一、无状态聊天系统的概念 无状态聊天系统意味着服务器不会在会话之间保留任何特定用户的信息。每次请求都被视为独立的,不依赖于之前的交互。这种设计简化了服务器端的复杂性,但同时也要求客户端负责存储和管理...

    UML面向对象分析与建模-【6】状态图.docx

    事件是UML中的一种基本概念,指的是在时间和空间上都占据一定位置的有意义的事情的规约。事件可以是同步的,也可以是异步的。既可以是外部事件,也可以是内部事件。外部事件指在系统和它的参与者之间传送的事件,而...

    EJB,有状态,无状态,实体bean笔记,及例子

    EJB规范定义了三种主要类型的bean:无状态session bean、有状态session bean和实体bean,每种类型都有其特定的用途和生命周期。 1. **无状态Session Bean** 无状态session bean是最基础的EJB类型,它们不维护任何...

    Redux是JavaScript状态容器提供可预测化的状态管理

    它们遵循“只读”原则,不能直接修改传入的状态,而是创建一个新的状态对象。 Redux 应用的生命周期包括以下步骤: - 用户交互触发组件发送一个`action`。 - `store` 接收到`action`后,会调用已注册的`reducer`,...

    java面向对象的概念

    比如,一个“人”对象可能有年龄和姓名作为状态,有跑步和说话作为行为。 - **类**是对一组具有相同特性的对象的抽象,是创建对象的模板。类定义了对象的状态和行为。例如,“汽车”类可以包含颜色、品牌等属性和...

Global site tag (gtag.js) - Google Analytics