編寫安全執行緒的JSP

來源:互聯網
上載者:User

JSP預設是以多線程方式執行的,這是JSP與ASP,PHP,PERL等指令碼語言不一樣的地方,也是它的優勢之一,但如果不注意多線程中的同步問題,會使所寫的JSP程式有難以發現的錯誤。下面以一個例子說明JSP中的多線程問題及解決方案。

一、JSP的中存在的多線程問題:

當用戶端第一次請求某一個JSP檔案時,服務端把該JSP編譯成一個CLASS檔案,並建立一個該類的執行個體,然後建立一個線程處理CLIENT端的請求。如果有多個用戶端同時請求該JSP檔案,則服務端會建立多個線程。每個用戶端請求對應一個線程。以多線程方式執行可大大降低對系統的資源需求,提高系統的並發量及回應時間.對JSP中可能用的的變數說明如下:

  1. 執行個體變數
    執行個體變數是在堆中分配的,並被屬於該執行個體的所有線程共用,所以不是安全執行緒的.
  2. JSP系統提供的8個類變數
    JSP中用到的OUT,REQUEST,RESPONSE,SESSION,CONFIG,PAGE,PAGECONXT是安全執行緒的,APPLICATION在整個系統內被使用,所以不是安全執行緒的.
  3. 局部變數
    局部變數在堆棧中分配,因為每個線程都有它自己的堆棧空間,所以是安全執行緒的.
  4. 靜態類
    靜態類不用被執行個體化,就可直接使用,也不是安全執行緒的.
  5. 外部資源:
    在程式中可能會有多個線程或進程同時操作同一個資源(如:多個線程或進程同時對一個檔案進行寫操作).此時也要注意同步問題.

二、下面的例子存在的多線程問題:

 

<%@ page import="
javax.naming.*,
java.util.*,
java.sql.*,
weblogic.common.*
" %>
 

<%
String name
String product;
long  quantity;

name=request.getParameter("name");
product=request.getParameter("product");
quantity=request.getParameter("quantity"); /*(1)*/
savebuy();
%>

<%!
public void  savebuy()
{
    /*進行資料庫操作,把資料儲存到表中*/
    try {
      Properties props = new Properties();
      props.put("user","scott");
      props.put("password","tiger");
      props.put("server","DEMO");  

      Driver myDriver = (Driver) iver").newInstance();
      conn = myDriver.connect("jdbc:weblogic:oracle", props);
      stmt = conn.createStatement();
   
      String inssql = "insert into buy(empid, name, dept) values (?, ?, ?,?)";
      stmt = conn.prepareStatement(inssql);

      stmt.setString(1, name);
      stmt.setString(2, procuct);   
      stmt.setInt(3, quantity);
      stmt.execute();
    }
    catch (Exception e)
    {
        System.out.println("SQLException was thrown: " + e.getMessage());
    }
    finally //close connections and     {
        try {
          if(stmt != null)
            stmt.close();
          if(conn != null)
            conn.close();
        } catch (SQLException sqle) {
            System.out.println("SQLException was thrown: " + sqle.getMessage());
        }
    }
}
%>

上面的程式類比網上購物中的一部分,把使用者在瀏覽器中輸入的使用者名稱,購買的物品名稱,數量儲存到表BUY中。在savebuy()函數中用到了執行個體變數,所以它不是安全執行緒的.因為:程式中的每一條語句都不是原子操作,如name=request.getParameter("name");在執行是會對應多個機器指令,在任何時候都可能因系統調度而轉入睡眠狀態,讓其他的線程繼續執行.如果線程A在執行到(1)的時候轉入睡眠狀態,線程B開始執行並改變QUANTITY的值,那麼當又到A執行時,它會從調用savebuy()函數開始執行,這樣它儲存到表中的QUANTITY是被線程B改過的值,那麼線程A對應的使用者所實際購買的數量與保持到表中的資料不一致.這是個很嚴重的問題.

 

三、解決方案

  1. 採用單線程方式
    在該JSP檔案中加上: ,使它以單線程方式執行,這時,仍然只有一個執行個體,所有用戶端的請求以串列方 式執行。這樣會降低系統的效能.
  2. 對函數savebuy()加synchronized進行線程同步,該JSP仍然以多線程方式執行,但也會降低系統的效能
    public synchronized void savebuy()
    {
           ......
    }
  3. 採用局部變數代替執行個體變數,函數savebuy()聲明如下:
    因為在savebuy()中使用的是傳給他的形參,是在堆棧中分配的,所以是安全執行緒的.
    public void savebuy(String name,String product, int quantity)
    {
          ......
    }

    調用方式改為:
    <%
    String name
    String product;
    long quantity;

    name=request.getParameter("name");
    product=request.getParameter("product");
    quantity=request.getParameter("quantity");
    savebuy(name,product,quantity)
    %>

    如果savebuy的參數很多,或這些資料要在很多地方用到,也可聲明一個類,並用他做參數,如:

    public class buyinfo
    {
          String name;
          String product;
          long quantity;
    }

    public void savebuy(buyinfo info)
    {
          ......
    }

    調用方式改為:
    <%
    buyinfo userbuy = new buyinfo();

    userbuy.name=request.getParameter("name");
    userbuy.product=request.getParameter("product");
    userbuy.quantity=request.getParameter("quantity");
    savebuy(userbuy);
    %>

     

所以最好是用3,因為1,2會降低系統的效能.
多線程問題一般只有在在大並發量訪問時,才有可能出現,並且很難重複出現,所以應在編程時就時刻注意。

 作者簡介
  dev2dev ID: xcjing,BEA 資深技術顧問,加入BEA中國多年,在門戶技術、RFID解決方案上有著豐富的經驗。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.