如何實現servlet得單線程模式

如何現實servlet的單線程模式

這個面試題挺經典的,可是網上很多朋友的回答題不達意,所以我在這裏就這個問題做一下探討。

網上朋友的回答是加入<%@ page isThreadSafe=”false”%>這條命令。天啊,我暈!這是什麼命令?是jsp的命令啊,怎麼會加入到servlet中呢?當然了,jsp的運行實質是servlet機制,這條命令是jsp頁面告訴容器編譯“我”的時候實現單線程。那我們看看他編譯後的servlet類和以前的servlet有什麼不同?沒有加入這條指令的頁面中servlet類定義是:

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {

………………………………//內部實現咱們大可以不看他。
}

而加入這個命令之後的類定義是:

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
SingleThreadModel {

…………………………//同樣省略實現細節

}

我想大家應該很清楚的發現:加入<@page isThreadSafe="false">之後servlet是實現了SingleThreadModel接口的。有興趣的朋友可以查下相關資料,其實這個接口在servlet2.4之後就廢除了。那麼爲什麼廢除?實現了這個接口查看代碼內容的時候卻發現什麼方法都沒添加,爲什麼?

其實這個接口只是一個標識,讓容器改變servlet生成策略的。

  默認的,servlet容器是隻創建servlet単實例,爲請求提供線程池,我們爲了能保證servlet的線程安全問題而不在servlet中添加實例屬性。

但是如果一個servlet實現了SingleThreadModel接口那容器在創建實例池,爲每個求情分配實例,當用戶請求結束時將實例歸還實例池。

這樣做真的安全嗎?非也!因爲每個請求都會分發一個servlet實例,對於同用戶下分發的不同的servlet來說很可能用到同一個session中的屬性數據,這樣當然出現了線程同步的問題,是不安全的!而且不同用戶也可能享用同一個context中的數據,也是不安全的。於是在servlet2.4中建議不再使用這樣的設置。

  這樣一來我們知道:如果非要實現servlet單線程那就要在servlet中實現SingleThreadModel接口,在jsp中添加<@ page isThreadSafe="false">命令。但是這是不被提倡的。

  也有網友疑問:讓servlet單線程而多實例本來不是爲了線程安全的嗎?爲什麼<@ page isThreadSafe=?>?的答案卻是false?

  我覺得這是個誤區,這樣設置真的是單線程嗎?那肯定不是了,其實這個設置只是要容器保證同一時刻只有一個線程能在servlet的service方法中執行,因爲默認的容器實例化servlet時時単實例,如果同時只有一個線程去管理這個唯一的servlet實例,那性能將是極其慢的,爲了解決這個問題,容器採取了servlet實例池的方式。每個請求一個線程,而一個線程一個servlet。

因爲這種方式並不是線程安全的,所以答案是false。

  終上所述:其實這道題目是指如果讓一個servlet實例對應一個線程,而不是一個servlet實例對應多個線程的默認方式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章