程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> .NET實例教程 >> 用.NET創建定時緩存

用.NET創建定時緩存

編輯:.NET實例教程

在先前的文章裡,我詳細討論了.Net緩存的簡單用法。不過那點用途還只能是這一話題的“開胃酒”。現在,我們更進一步,在那篇文章所開發的緩存基礎上添加條目在緩存中的過期功能。

清單A的內容就是上次我們開發的有關代碼。

新緩存及其改進
為了創建定時緩存,我們首先得確定某個對象是否已經到期了。出於這篇文章討論范圍,我假設用戶能夠確定准確的對象超期日期。這樣,在將來還可以再改進為允許在緩存中存放的對象自己確定它們的過期日期。

我們首先修改insertCachedObject方法以支持緩存中對象的過期功能。當對象插入緩存時,該方法會給用戶提供一個對象過期日期。這個日期參數被稱為dtExpiration。insertCachedObject方法則存儲經由該參數傳遞的過期日期。完成這一目標有若干方法。例如,我們可以創建一個封裝對象,其中包含了日期和對象屬性。如果這樣做的話,insertCachedObject方法就會創建封裝對象的實例並提供給它兩個屬性。我們選擇相比更簡單些的第二個方案:創建和聲明第2個哈希散列表,並且指定它同第一個哈希散列表並行運行。這第二個哈希散列表叫做htExpiration。

對 insertCachedObject 方法的修改請見清單B。

現在,我們需要想辦法發現過期的條目。在通過getCachedObject方法發出請求時,簡單而且也是最偷懶的辦法是檢查每個緩沖對象。因為直到發出處理請求才調出過期對象,所以這是一種較差的算法。而且很有可能在時間上具有一定的不確定性。雖然這些到期對象駐留在緩存裡,可是它們消費著珍貴的內存資源,這對應用程序的性能具有極其不利的影響。

不用這種偷懶的辦法,我們創建一個後台線程反復檢查htExpiration哈希表。

於是我們創建一個名叫TheReaperThread的類,這個類有一個方法負責建立無限循環。該類還被聲明為內部類,因為它只用在CustomCache對象的上下文環境內。該類的全部代碼請見清單C。

你得對清單C中的Shared Constructor注意了,它負責創建新的線程並啟動該線程。我們接下來創建測試程序保證緩存運行正常。測試程序見清單D,該程序是一個控制台程序,當然也可以用.Net Framework 把以上程序當作項目來創建。


小結
定時緩存就這樣完全實現了。雖然在功能上還比較簡單,而且不能通知緩存的用戶條目在什麼時候到期,也不允許對象確定它們自己的過期算法。不過在這種簡單緩存的基礎上,將來我們還可以討論開發新的功能,比如分派、內存管理等等。

Listing A


'Defines a Public Class called CustomCache
Public Class CustomCache
'Declares the hashtable use to store everything put into the cache.
'Since ht is shared there it follows a Singleton pattern
Private Shared ht As System.Collections.Hashtable
'A shared Constructor runs when the class is referenced very first time.
Shared Sub New()
'Instantiates the Hashtable
ht = New Hashtable()
End Sub
'A private constructor prevents clIEnts instantiating CustomCache Object
Private Sub New()
End Sub
'Shared method used to put objects into the cache
Public Shared Sub insertCachedObject(ByVal key As Object, ByVal o As Object)
ht.Add(key, o)
End Sub
'Shared method used to retrIEve objects from the cache
Public Shared Function getCachedObject(ByVal key As Object) As Object
Return ht.Item(key)
End Function
End Class


Listing B


Public Shared Sub insertCachedObject(ByVal key As Object, ByVal o As Object, ByVal dtExpiration As Date)
ht.Add(key, o)
'Add the expiration date to the second hashtable using the same key
htExpiration.Add(key, dtExpiration)
End Sub


Listing C


'Imports the Threading namespace - the ThreadStart object resides in it
Imports System.Threading
'Defines a Public Class called CustomCache
Public Class CustomCache
'Declares the hashtable use to store everything put into the cache.
'Since ht is shared there it follows a Singleton pattern
Private Shared ht As System.Collections.Hashtable
Private Shared htExpiration As System.Collections.Hashtable
'This class is responsible for finding expired objects and removing them from the cache
'this class is named TheReaperThread in remembrance of the Grim Reaper!
Class TheReaper
'This method will reap until the cows come home.
Sub ReapBabyReap()
Dim dt As Date
While True
'Output message to the console
Console.WriteLine("The reaper thread is looking for expired objects...")
'Declare an Enumerator - Enumerator are used to iterate collections
Dim myEnumerator As IDictionaryEnumerator
'Instantiate Enumerator
myEnumerator = htExpiration.GetEnumerator()
'Loops through all items
While myEnumerator.MoveNext()
'get the expiration date
dt = myEnumerator.Value
'Output to the console
Console.Write("Key: " + ControlChars.Tab + "{0}, Expires: " + ControlChars.Tab + "{1}", myEnumerator.Key, dt.ToString)
'Compare the date of expiration with the current date and time.
'If its less than or equal to zero in value then item gone
If Date.Compare(dt, Now()) <= 0 Then
'Output to the console
Console.WriteLine(" EXPIRED - Removing")

'Remove the expired item from the main hashtable
ht.Remove(myEnumerator.Key)
'don't forget to remove the expired item htExpiration.Remove(myEnumerator.Key)
' HACK Need to refresh the enumeration.
' This must be done to avoid the exception which occurs otherwise.
' This will cause the loop to restart from the beginning and may
' lead to certain items positioned
' at the end of the hashtable to remain longer than they would otherwise.
' This can be considered a hack and should be revisited
myEnumerator = htExpiration.GetEnumerator()
Else
'output to the console
Console.WriteLine(" Not Expired")
End If
'Give the reaper a break, he doesn't need to check every single second does he?
Thread.Sleep makes the current thread pause execution for specifIEd number of
'milliseconds. This value could be set as a public property of the class.
Thread.Sleep(5000)
End While
End While
End Sub
End Class
'A shared Constructor runs when class referenced the first time.
Shared Sub New()
'Instantiates the Hashtable
ht = New Hashtable()
'Instantiates the Expiration Hashtable
htExpiration = New Hashtable()
'Declare and instantiate the TheReaperThread
Dim grimReaper As New TheReaper()
'Create a ThreadStart object, passing the address of grimReaper.ReapBabyReap.
'ThreadStart is a delegate! We will learn more about these in the next article.
Dim otter As New ThreadStart(AddressOf grimReaper.ReapBabyReap)
'Create a Thread object.
Dim oThread As New Thread(otter)
'Starting the thread invokes the ThreadStart delegate.
oThread.Start()
End Sub
'A private constructor prevents clIEnts from instantiate the CustomCache Object
Private Sub New()
End Sub
'Shared method used to put objects into the cache
'dtExpiration is the date of expiration parameter
Public Shared Sub insertCachedObject(ByVal key As Object, ByVal o As Object, ByVal dtExpiration As Date)
ht.Add(key, o)
'Add the expiration date to the second hashtable using the same key
htExpiration.Add(key, dtExpiration)
End Sub
'Shared method used to retrIEve objects from the cache
Public Shared Function getCachedObject(ByVal key As Object) As Object
Return ht.Item(key)
End Function
End Class


Listing D


Module TestCache
Sub Main()
'Creates a String which contains the Alphabet A..Z
Dim s As New String("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
'Inserts the String into the Cache using a string key of "Alphabet"
'Sets the expiration date to the current date and time plus one minute
UnitTest.CustomCache.insertCachedObject("Alphabet", s, Now().AddMinutes(1))
'Declares a Second String called s1
Dim s1 As String
'RetrIEves the cache object which matches the key of "Alphabet"
s1 = UnitTest.CustomCache.getCachedObject("Alphabet")
'This should output the alphabet A..X
Console.WriteLine(s1)
'Don't hit the enter key until see item expired in the console window
Console.ReadLine()
'Declares a Third String called s1
Dim s3 As String
'RetrIEves the cache object which matches the key of "Alphabet"
s3 = UnitTest.CustomCache.getCachedObject("Alphabet")
'This should output the alphabet A..X
Console.WriteLine(s3)
'By performing a Console.readline it allows us to see the
' output of the console window prior to its closing
Console.ReadLine()
End Sub
End Module

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved