前面介紹過IoSessionRecycler是負責回收不再使用的會話的介面,ExpiringSessionRecycler是其一個實作類別,用於回收逾時失效的會話。
private ExpiringMap<Object, IoSession> sessionMap;//待處理的會話集
private ExpiringMap<Object, IoSession>.Expirer mapExpirer;//負責具體的回收工作
sessionMap的鍵是由本地地址和遠端地址共同組成的,值是這兩個地址對應的會話。
Expirer類實現了Runnable介面,這個線程負責監控ExpiringMap,並把ExpiringMap中超過閥值的元素從ExpiringMap中移除。這個線程調用了setDaemon(true),因此是作為守護線程在後台運行。具體的處理過程如下:
Java代碼
- private
void
processExpires()
- {
- long
timeNow = System.currentTimeMillis();
//目前時間
- for
(ExpiringObject o : delegate.values())
- {
- if
(timeToLiveMillis <=
0
)
- {
- continue
;
- }
- long
timeIdle = timeNow - o.getLastAccessTime();
//時間差
- if
(timeIdle >= timeToLiveMillis)
- {//逾時
- delegate.remove(o.getKey());
- for
(ExpirationListener<V> listener : expirationListeners)
- {//呼叫監聽者
- listener.expired(o.getValue());
- }
- }
- }
- }
private void processExpires() { long timeNow = System.currentTimeMillis();//目前時間 for (ExpiringObject o : delegate.values()) { if (timeToLiveMillis <= 0) { continue; } long timeIdle = timeNow - o.getLastAccessTime();//時間差 if (timeIdle >= timeToLiveMillis) {//逾時 delegate.remove(o.getKey()); for (ExpirationListener<V> listener : expirationListeners) {//呼叫監聽者 listener.expired(o.getValue()); } } } }
啟動/關閉逾時檢查線程都需要進行封鎖機制,這裡使用的是讀寫鎖:
Java代碼
- private
final
ReadWriteLock stateLock =
new
ReentrantReadWriteLock();
-
- public
void
startExpiring()
- {
- stateLock.writeLock().lock();
- try
- {
- if
(!running)
- {
- running = true
;
- expirerThread.start();
- }
- }
- finally
- {
- stateLock.writeLock().unlock();
- }
- }
- public
void
stopExpiring()
- {
- stateLock.writeLock().lock();
- try
- {
- if
(running)
- {
- running = false
;
- expirerThread.interrupt();
- }
- }
- finally
- {
- stateLock.writeLock().unlock();
- }
- }
private final ReadWriteLock stateLock = new ReentrantReadWriteLock(); public void startExpiring() { stateLock.writeLock().lock(); try { if (!running) { running = true; expirerThread.start(); } } finally { stateLock.writeLock().unlock(); } } public void stopExpiring() { stateLock.writeLock().lock(); try { if (running) { running = false; expirerThread.interrupt(); } } finally { stateLock.writeLock().unlock(); } }
會話逾時監聽者:
Java代碼
- private
class
DefaultExpirationListener
implements
- ExpirationListener<IoSession> {
- public
void
expired(IoSession expiredSession) {
- expiredSession.close();//關閉逾時的會話
- }
- }