程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> JSP編程 >> 關於JSP >> 編寫線程安全的JSP應用程序

編寫線程安全的JSP應用程序

編輯:關於JSP

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

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

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

實例變量

實例變量是在堆中分配的,並被屬於該實例的所有線程共享,所以不是線程安全的。

JSP系統提供的8個類變量,JSP中用到的OUT,REQUEST,RESPONSE,SESSION,CONFIG,PAGE,PAGECONXT是線程安全的,APPLICATION在整個系統內被使用,所以不是線程安全的。

局部變量

局部變量在堆棧中分配,因為每個線程都有它自己的堆棧空間,所以是線程安全的。

靜態類

靜態類不用被實例化,就可直接使用,也不是線程安全的。

外部資源:

在程序中可能會有多個線程或進程同時操作同一個資源(如:多個線程或進程同時對一個文件進行寫操作).此時也要注意同步問題。

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

<%@ 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. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved