1. 程式人生 > >SpringMVC學習筆記:單例與並發問題

SpringMVC學習筆記:單例與並發問題

一個 獲得 app parseint 本地服務 屬性 als min c學習

Spring中的Bean默認都是單例(singleton),Spring中Bean的scope屬性有五種類型:

  1. singleton 表示在spring容器中的單例,通過spring容器獲得該bean時總是返回唯一的實例
  2. prototype 表示每次獲得bean都會生成以新的對象
  3. request 表示在一次Htttp請求內有效(只適用於web應用)
  4. session 表示在一個用戶會話內有效(只適用於web應用)
  5. globalSession 表示在全局會話內有效(只適用於web應用)

SpringMVC中Controller類默認Scope是單例,因而在Controller類中使用成員變量時需要註意並發的問題,舉例說明:

@Controller
public class ExampleAction {
private int singletonInt=1;
@RequestMapping(value
= "/test") @ResponseBody public String singleton(HttpServletRequest request, HttpServletResponse response) throws Exception { String data=request.getParameter("data"); if(data!=null
&&data.length()>0){ try{ int paramInt= Integer.parseInt(data); singletonInt = singletonInt + paramInt; } catch(Exception ex){ singletonInt+=10; } }else{ singletonInt+=1000; }
return String.valueOf(singletonInt); } }

請求三次 http://localhost:8080//test?data=15 ,得到的結果分別是15 30 45,由此說明Controller是單例

單例的好處也很明顯:不用每次創建Controller,減少了對象創建和垃圾收集的時間。

當有多個用戶同時請求一個服務時,容器會給每一個請求分配一個線程,各個線程是不會相互影響,舉例如下:

@RequestMapping(value = "/sleepdata")
@ResponseBody
public String switcher(HttpServletRequest request, HttpServletResponse response) throws Exception {
  String sleep = request.getParameter("sleep");
  if (sleep.equals("on")) {
      Thread.currentThread().sleep(100000);
       return "sleep on";
   } else {
       return sleep;
  }
}

分別發送兩個請求,

第一個請求:http://localhost:8080/sleepdata?sleep=on

第二個請求:http://localhost:8080/sleepdata?sleep=test

驗證結果:第一個請求發出去以後,本地服務器等待100s,然後返回結果”sleep on”,在本地服務器等待的者100s當中,發送第二個請求,直接返回結果”test”。說明之間的線程是不互相影響的

單例的狀態改變:體現為該單例的成員屬性值的修改

有狀態對象(Stateful Bean):就是有成員變量的對象,可以保存數據,是非線程安全的

無狀態對象(Stateless Bean):就是沒有實例變量的對象,不能保存數據,是不變類,是線程安全的

Spring對一些Bean中非線程安全狀態采用ThreadLocal進行處理,讓它們也成為線程安全的狀態

內容來源網絡,非原創,侵刪

SpringMVC學習筆記:單例與並發問題