建站學院(LieHuo.Net)編程綜合 PHP的工作模型非常特殊。從某種程度上說,PHP和ASP、ASP.NET、JSP/Servlet等流行的Web技術,有著本質上的區別。
以Java為例,Java在Web應用領域,有兩種技術:Java Servlet和JSP(Java Server Page)。Java Servlet是一種特殊類型的Java程序,它通過實現相關接口,處理Web服務器發送過來的請求,完成相應的工作。JSP在形式上是一種類似于PHP 的腳本,但是事實上,它最后也被編譯成Servlet。
也就是說,在Java解決方案中,JSP和Servlet是作為獨立的Java應用程序執行的,它們在初始化之后就駐留內存,通過特定的接口和 Web服務器通信,完成相應工作。除非被顯式地重啟,否則它們不會終止。因此,可以在JSP和Servlet中使用各種緩存技術,例如數據庫連接池。
ASP.NET的機制與此類似。至于ASP,雖然也是一種解釋型語言,但是仍然提供了Application對象來存放應用程序級的全局變量,它依托于ASP解釋器在IIS中駐留的進程,在整個應用程序的生命期有效。
PHP卻完全不是這樣。作為一種純解釋型語言,PHP腳本在每次被解釋時進行初始化,在解釋完畢后終止運行。這種運行是互相獨立的,每一次請求都會創建一個單獨的進程或線程,來解釋相應的頁面文件。頁面創建的變量和其他對象,都只在當前的頁面內部可見,無法跨越頁面訪問舊電腦回收。
在終止運行后,頁面中申請的、沒有被代碼顯式釋放的外部資源,包括內存、數據庫連接、文件句柄、Socket連接等,都會被強行釋放。也就是說,PHP無法在語言級別直接訪問跨越頁面的變量,也無法創建駐留內存的對象。見下例:
以下為引用的內容: <?php class StaticVarTester { public static $StaticVar = 0; } function TestStaticVar() { TestStaticVar(); |
在這個例子中,定義了一個名為StaticVarTester的類,它僅有一個公共的靜態成員$StaticVar,并被初始化為0。然后,在 TestStaticVar()函數中,對StaticVarTester :: $StaticVar進行累加操作,并將它打印輸出。
熟悉 Java或C++的開發者對這個例子應該并不陌生。$StaticVar作為StaticVarTester類的一個靜態成員,只在類被裝載時進行初始化,無論StaticVarTester類被實例化多少次,$StaticVar都只存在一個實例,而且不會被多次初始化。因此,當第一次調用 TestStaticVar()函數時,$StaticVar進行了累加操作,值為1,并被保存。第二次調用TestStaticVar()函數,$ StaticVar的值為2。
打印出來的結果和我們預料的一樣:
StaticVarTester :: StaticVar = 1
StaticVarTester :: StaticVar = 2
但是,當瀏覽器刷新頁面,再次執行這段代碼時,不同的情況出現了。在Java或C++里面,$StaticVar的值會被保存并一直累加下去,我們將會看到如下的結果:
StaticVarTester :: StaticVar = 3
StaticVarTester :: StaticVar = 4
…
但是在PHP中,由于上文敘及的機制,當前頁面每次都解釋時,都會執行一次程序初始化和終止的過程。也就是說,每次訪問時,StaticVarTester都會被重新裝載,而下列這行語句
public static $StaticVar = 0;
也會被重復執行。當頁面執行完成后,所有的內存空間都會被回收,$StaticVar這個變量(連同整個StaticVarTester類)也就不復存在。因此,無論刷新頁面多少次,$StaticVar變量都會回到起點:先被初始化為0,然后在TestStaticVar()函數調用中被累加。所以,我們看到的結果永遠是這個:
StaticVarTester :: StaticVar = 1
StaticVarTester :: StaticVar = 2
PHP這種獨特的工作模型的優勢在于,基本上解決了令人頭疼的資源泄漏問題。Web應用的特點是大量的、短時間的并發處理,對各種資源的申請和釋放工作非常頻繁,很容易導致泄漏。
上一篇 Access數據庫技術(35)