1. 程式人生 > >有狀態和無狀態的區別

有狀態和無狀態的區別

基本概念: 

有狀態就是有資料儲存功能。有狀態物件(Stateful Bean),就是有例項變數的物件 ,可以儲存資料,是非執行緒安全的。在不同方法呼叫間不保留任何狀態。

無狀態就是一次操作,不能儲存資料。無狀態物件(Stateless Bean),就是沒有例項變數的物件 .不能儲存資料,是不變類,是執行緒安全的。

程式碼更好理解:

Java程式碼

  
public   class  StatefulBean {   
  
     public   int  state;   
     // 由於多執行緒環境下,user是引用物件,是非執行緒安全的   
     public  User user;   
  
     public   int  getState() {   
         return  state;   
    }   
  
     public   void  setState( int  state) {   
         this .state = state;   
    }   
  
     public  User getUser() {   
         return  user;   
    }   
  
     public   void  setUser(User user) {   
         this .user = user;   
    }   
}   
  
  
public   class  StatelessBeanService {   
  
     // 雖然有billDao屬性,但billDao是沒有狀態資訊的,是Stateless Bean.   
    BillDao billDao;   
  
     public  BillDao getBillDao() {   
         return  billDao;   
    }   
  
     public   void  setBillDao(BillDao billDao) {   
         this .billDao = billDao;   
    }   
  
     public  List<User> findUser(String Id) {   
return   null ;   
    }   
}  


單例模式中的有狀態和無狀態: 
單例類可以是有狀態的(stateful),一個有狀態的單例物件一般也是可變(mutable)單例物件 。 有狀態的可變的單例物件常常當做狀態庫(repositary)使用。比如一個單例物件TaskCache(Spring中配為singleton)可以 持有一個AtomicLong型別的屬性,用來給一個系統提供一個數值惟一的序列號碼,作為任務通迅管理的ID生成器。同時,一個單例類也可以持有一個聚 集,從而允許儲存多個狀態,如示例中的ExpiringMap快取任務列表。
程式碼示例:

Java程式碼

import  java.util.concurrent.atomic.AtomicLong;   
  
import  org.apache.mina.util.ExpiringMap;   
  
  
public   class  TaskCache {   
  
     // 請求超時   
     private   short  requestTimeout;   
  
     // 這個快取Map是執行緒安全,並且有定時超時功能   
     private  ExpiringMap<String, Object> tasksMap =  new  ExpiringMap<String, Object>();   
  
     // 執行緒安全的原子類,示例有狀態的單例類   
     private   static  AtomicLong seqNo =  new  AtomicLong( 1 );   
  
     // 示例有狀態的單例類   
     public  Long nextSeqNo() {   
         return  seqNo.getAndIncrement();   
    }   
  
     public   void  setRequestTimeout( short  requestTimeout) {   
         this .requestTimeout = requestTimeout;   
    }   
  
     // 啟動過期檢測   
     public   void  startExpiring() {   
        tasksMap.getExpirer().setTimeToLive(requestTimeout);   
        tasksMap.getExpirer().startExpiringIfNotStarted();   
    }   
  
     // 停止過期檢測   
     public   void  stopExpiring() {   
        tasksMap.getExpirer().stopExpiring();   
    }   
  
     // 取任務列表.   
     public  Object getTasks(String key) {   
         return  tasksMap.get(key);   
    }   
  
     // 去除任務列表.   
     public  Object removeTasks(String key) {   
         return  tasksMap.remove(key);   
    }   
  
     // 新增任務列表.   
     public   void  addTasks(String key, Object value) {   
        tasksMap.put(key, value);   
    }   
}  



單例類也可以是沒有狀態的(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程式碼

  
public   class  UnSafeServlet HttpServlet{   
       
    User user;   
    PrintWriter out;   
       
     public   void  doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{   
         //do something...   
    }   
}  


Out,Request,Response,Session,Config,Page,PageContext是執行緒安全的,Application在整個系統內被使用,所以不是執行緒安全的.

2.Struts1也是基於單例模式實現,也就是隻有一個Action例項供多執行緒使用。預設的模式是前臺頁面資料通過actionForm傳入,在 action中的excute方法接收,這樣action是無狀態的,所以一般情況下Strunts1是執行緒安全的。如果Action中用了例項變數,那 麼就變成有狀態了,同樣是非執行緒安全的。像下面這樣就是執行緒不安全的。

Java程式碼

  
public   class  UnSafeAction1  extends  Action {   
  
     // 因為Struts1是單例實現,有狀態情況下,物件引用是非執行緒安全的   
    User user;   
  
     public   void  execute() {   
         // do something...   
    }   
  
     public  User getUser() {   
         return  user;   
    }   
  
     public   void  setUser(User user) {   
         this .user = user;   
    }   
}    

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等機制,所以無狀態的不變機制,也可以避免產生死鎖現象。

相關推薦

狀態狀態區別

基本概念:  有狀態就是有資料儲存功能。有狀態物件(Stateful Bean),就是有例項變數的物件 ,可以儲存資料,是非執行緒安全的。在不同方法呼叫間不保留任何狀態。 無狀態就是一次操作,不能儲存資料。無狀態物件(Stateless Bean),就是沒有例項變數的物件 .

併發程式設計實戰(1):執行緒安全性之狀態狀態物件

程序和執行緒的區別 程序是具有一定獨立功能的程式關於某個資料集合上的一次執行活動,程序是系統進行資源分配和排程的一個獨立單位. 執行緒是程序的一個實體,是CPU排程和分派的基本單位,它是比程序更小的能獨立執行的基本單位. 程序在執行過程中擁有獨立的記憶體單元,程序

狀態狀態的Servlet

有狀態和無狀態的Servlet 有狀態 有狀態就是有資料的儲存功能.有狀態物件(Stateful Bean) 有例項變數的物件,可以儲存資料,是非執行緒安全的.在不同的方法呼叫間不保留任何的狀態.無狀態 無狀態就是一次操作,不能儲存資料.無狀態物件(Stateless Bean) 沒有例項變數的物件

狀態狀態服務

很多 技術 分享 是否 建議 關心 http 圖片 復制  有狀態服務器和無狀態服務器 對服務器程序來說,有兩個基本假設十分重要,究竟服務器是基於狀態請求還是無狀態請求。狀態化的判斷是指兩個來自相同發起者的請求在服務器端是否具備上下文關系。如果是狀態化請求,那麽服務器端一

淺析權限認證中的狀態狀態

總結 有一個 eth 返回 alt 配置 客戶端信息 傳遞 主動 前言 我們在設計構建一個系統的時候,權限管理和用戶認證是最基本功能,其中關於用戶認證這塊是一個比較常見的模塊。在已有的方案中,我們最常見的就是保存到 tomcat 中的 session 對象中。隨著微服務的興

狀態登入狀態登入的概念

1,這是有狀態登入 缺點是什麼? • 服務端儲存大量資料,增加服務端壓力 • 服務端儲存使用者狀態,無法進行水平擴充套件 • 客戶端請求依賴服務端,多次請求必須訪問同一臺伺服器(如果叢集了,相當於啟動了多個tomcat,就需要在多個tomcat之間共享資料) 簡單來說,

聊聊系統設計:狀態狀態

公司 bre 就會 信息 時代 www. quest tolerance 呵呵 網站登錄校驗,很普通的一個功能 對於這個功能我們要如何實現? 先分析一下登錄校驗是個啥意思 舉個栗子,比如我們在登陸頁輸入用戶名密碼,登錄了社交網站 這時候想去看自己的新鮮事,卻告訴我請先輸入用

css 樣式中類之間空格空格的區別

看到 .header .content      .header.content  .header>.content  這幾個選擇器的意思 .header.content     

符號符號的區別 資料類型範圍 sizeof()關鍵字

有符號和無符號的區別 資料類型範圍 sizeof()關鍵字 有符號和無符號的區別 1)有符號,最高位是符號位,如果是1代表是負數,如果為0代表為正數 2)無符號,最高位不是符號位,是數的一部分,無符號不可能是負數 #include <std

CSS選擇器:#id.class中間空格空格的區別

相信大家都知道 .class1 .class2 和 .class1.class2 是兩種不同的選擇規則,但具體怎樣不同呢? 首先中間有空格的情況:是選擇到.class1類下的.class2類子節點,即.class2類的節點要是.class1類子節點 .class1 { col

Java_Html_雜七雜八_路徑中//的區別,.././的區別

Java/Html中 有/ 和 無/ 的區別。 Java專案中: 不加  /    就是獲取的當前路徑, 加    /      就是從根目錄 獲取子路徑(根目錄為WebRoot)。 解釋:通常在

基於docker打造實現自動化整合狀態持續交付流水線

專案背景 此專案是我在我第一家公司,一家做p2p的互金公司做的專案。當時我主要負責公司所有專案在預釋出環境和生產環境部署。公司早期的技術骨幹多來自BAT,所以有著很鮮明網際網路公司的基因,採用的也是敏捷開發模式。所以是靠著持續迭代的方式,來不斷優化改進產品的。

tcp協議是面向連線的,而http是狀態的,面向連線狀態怎麼感覺好像優點矛盾呢?

 不矛盾,一個是面向連結的,一個是無連線的。面向連結的可靠些,無連線的就不那麼可靠。主要是因為這兩個協議所處的層不一樣。網際網路的設計者認為,使用者層應是簡單的,直接的。所以無連線的設計能夠簡化裝置的成本,利於網際網路的

lua學習筆記day04-----狀態狀態的迭代器

在解釋無狀態和多狀態的迭代器之前,我們需要先了解一下泛型for是如何和迭代函式一起工作的。 a = {"one","two","three"} function gc(c) local k = 0 return function ()

IPv6系列-徹底弄明白狀態狀態配置IPv6地址

深入研究自動分配IPv6地址的Stateless(無狀態)與Stateful(有狀態)方式 小慢哥的原創文章,歡迎轉載 目錄 ▪ 一. Link-Local Address的生成方式 ▪ 二. Global Address的生成方式 ▪ 三. RA報文中3個關鍵的Flag ▪ 四. 流程示意圖 ▪ 五.

符號符號整型數據溢出問題

signed BE AI pos 技術分享 south 符號整型 有符號 mark 無符號數都有“unsigned”標誌,如果沒有“unsigned”標誌,則程序默認該數為有符號數“signed”。無符號數可正可負 ,有符號數一定為正。由於有符號與無符號數所占用的字節數相同

$?:退出狀態退出狀態

mage image pin 遇到 ech bubuko 狀態 例如 執行 $? 變量保存最近的命令退出狀態 進程使用退出狀態來報告成功或失敗 ?0 代表成功,1-255代表失敗 ?例如: ping -c1 -W1 hostdown &> /dev/null

Atitit 持久化 Persistence概念的藝術 目錄 1. 持久化是將程式資料在持久狀態瞬時狀態間轉換的機制。 1 2. DBC就是一種持久化機制。檔案IO也是一種持久化機制。 2 3.

Atitit 持久化 Persistence概念的藝術   目錄 1. 持久化是將程式資料在持久狀態和瞬時狀態間轉換的機制。 1 2. DBC就是一種持久化機制。檔案IO也是一種持久化機制。 2 3. 日常持久化的方法 2 4. 理解與分類 3 4.1

谷歌地圖偏離偏離

谷歌地圖有偏離和無偏離 谷歌的影像地圖分為兩類,一類是谷歌地球(Google Earth),一類是谷歌地圖(Google Map),其中谷歌地球又分為谷歌地球的影像和谷歌高程,谷歌地圖又分為谷歌衛星、谷歌電子和谷歌地形,各種地圖有無偏移見圖。 高德地圖,高德地圖分為高德衛星和高德電子地

C++符號符號之間的轉換

先來看一個程式: #include<iostream> int main() { unsigned a=5; int b=-10; std::cout<<b+b<<std::endl;//正常輸出 std