前段時間開發(fā)短信收發(fā)系統(tǒng),遇到一個問題,就是有n個對象都可以通過Mobile對象發(fā)短信,但同一時刻只允許一個對象進(jìn)行操作。所以設(shè)計了一個客戶限制管理器的對象來解決,但由于種種原因沒有用到實際系統(tǒng)中。后來經(jīng)過仔細(xì)考慮,發(fā)現(xiàn)它不僅可以用于端口的管理,還可用于其他需要針對客戶訪問數(shù)量進(jìn)行限制的各種服務(wù)中去。----這里的“客戶”是指要操作該管理器的對象
/**
* 客戶限制管理器的抽象類
* 此抽象類實現(xiàn)了對客戶訪問的限制,當(dāng)一個客戶訪問該服務(wù)時,可以通過halt(long guestid)方法阻止其他客戶進(jìn)行
* 訪問,防止多個客戶同時訪問產(chǎn)生的沖突。例如:對通訊端口的訪問等。
*/
public abstract class GuestManager {
/**
* 時間:一分鐘
*/
protected static final long ONE_MINUTE = 60L * 1000L;
/**
* 時間:一小時
*/
protected static final long ONE_HOUR = 60L * ONE_MINUTE;
/**
* 自動清理客戶記錄的間隔時間
*/
private long cleanInterval;
/**
* 客戶記錄<客戶標(biāo)識,最近訪問時間>
*/
private Hashtable guests;
/**
* 當(dāng)前限制的客戶
*/
private long limitGuest;
/**
* 自動清除過期客戶的線程
*/
private Thread autoCleanThread;
/**
* 客戶注冊
*
* @return 返回分配給客戶端的標(biāo)識,如果注冊失敗,返回-1
*/
public long login() {
long guestid = -1L;
// 增加客戶記錄
Hashtable guests = getGuests();
if (guests != null) {
guestid = System.currentTimeMillis();
guests.put("" + guestid, "" + guestid);
update(guestid);
// if (guests.size() == 1)
// connect();
}
return guestid;
}
/**
* 檢查客戶是否已經(jīng)注冊
*
* @param guestid
* 客戶標(biāo)識
* @return 如果客戶已經(jīng)注冊返回true,否則返回false
*/
public boolean isLogin(long guestid) {
boolean flag = false;
if (guestid > 0) {
Hashtable guests = getGuests();
if (guests != null)
flag = guests.containsKey("" + guestid);
if (flag)
update(guestid);
}// end if (guestid > 0)
return flag;
}
/**
* 注銷客戶
* 如果仍有其他客戶在使用此對象,則僅僅注銷guestid客戶,否則調(diào)用disconnect()方法關(guān)閉連接。
*
* @param guestid
* 客戶標(biāo)識
* @return 返回是否成功注銷
*/
public void logout(long guestid) {
Hashtable guests = getGuests();
if (guests != null) {
if (guestid > 0 && guests.containsKey("" + guestid)) {
guests.remove("" + guestid);
}// end if (guestid > 0 && getGuests().containsKey("" +
// guestid))
}// end if (guests != null)
}
/**
* 限制
* 如果某一客戶調(diào)用了該方法,那么其他客戶將無法訪問,直至該客戶調(diào)用resume()釋放。
*
* @param guestid
* 中斷標(biāo)識
* @return 返回是否成功中斷
*/
public boolean limit(long guestid) {
boolean flag = false;
if (isLogin(guestid)) {
update(guestid);
if (isLimit(guestid))
return flag;
limitGuest = guestid;
flag = true;
}// end if (isLogin(guestid))
return flag;
}
/**
* 釋放
*
* @param guestid
* 客戶標(biāo)識
* @return 返回是否釋放成功
*/
public boolean resume(long guestid) {
boolean flag = false;
if (isLogin(guestid)) {
update(guestid);
if (limitGuest == guestid) {
limitGuest = -1L;
}// end if(haltGuest == guestid)
flag = !isLimit();
}
return flag;
}
/**
* 是否限制其他客戶調(diào)用
*
* @return 返回是否限制其他客戶調(diào)用
*/
protected boolean isLimit() {
boolean flag = false;
if (limitGuest > 0) {
long lasttime = Long.parseLong((getGuests().get(
"" + limitGuest)));
if (lasttime > 0) {
// 如果10分鐘內(nèi)無響應(yīng),則注釋放該客戶的中斷
long time = System.currentTimeMillis() - 10L
* ONE_MINUTE;
if (time < lasttime)
flag = true;
else
limitGuest = -1;
}
}// end if(this.id <= 0)
return flag;
}
/**
* 該客戶是否被限制訪問
*
* @param haltId
* 客戶標(biāo)識
* @return 返回true表示禁止訪問,false表示可以訪問
*/ public boolean isLimit(long guestid) {
boolean flag = true;
if (isLogin(guestid)) {
update(guestid);
flag = isLimit();
if (flag) {
if (guestid > 0 && limitGuest == guestid)
flag = false;
}// end if(flag)
}
return flag;
}
/**
* 取得當(dāng)前限制客戶的標(biāo)識(該標(biāo)識是該管理器為客戶分配的一個標(biāo)識)
*
* @return 返回當(dāng)前限制客戶的標(biāo)識
*/
protected long getLimitGuest() {
return limitGuest;
}
/**
* 更新客戶最近使用時間
*
* @param guestid
* 客戶標(biāo)識
*/
protected void update(long guestid) {
runThread();
Hashtable guests = getGuests();
if (guests != null && guests.containsKey("" + guestid))
guests.put("" + guestid, ""
+ System.currentTimeMillis());
}
/**
* 運行監(jiān)聽線程
*/
protected void runThread() {
// 客戶自動清理線程
if (autoCleanThread != null && !autoCleanThread.isAlive())
autoCleanThread = null;
if (autoCleanThread == null) {
autoCleanThread = new AutoCleanThread();
autoCleanThread.start();
}// end if (autoCleanThread == null)
}
/**
* 設(shè)置自動清理客戶記錄的間隔時間
*
* @param time
* 間隔時間(毫秒)
*/
public void setCleanInterval(long time) {
if (time > 0)
cleanInterval = time;
}
/**
* 取得自動清理客戶記錄的間隔時間
*
* @return 返回自動清理客戶記錄的間隔時間(毫秒)
*/
public long getCleanInterval() {
return cleanInterval;
}
/**
* 取得客戶記錄
*
* @return 返回客戶記錄。格式為<客戶標(biāo)識,最近訪問時間>
*/
protected Hashtable getGuests() {
if (guests == null)
guests = new Hashtable();
return guests;
}
/**
* 輸出錯誤信息
*
* @param err
*/
public abstract void trace(String err);
/**
* 自動清除超時的客戶端的線程
*
*/
private class AutoCleanThread extends Thread {
public void run() {
trace("AutoCleanThread thread start runing...");
long interval = ONE_HOUR / 4L;
if (getCleanInterval() > 0)
interval = getCleanInterval();
while (autoCleanThread == this && getGuests().size() > 0) {
long time = System.currentTimeMillis()
- ONE_HOUR / 2L;
Enumeration> keys = getGuests().keys();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
if (key != null) {
long lasttime = Long.parseLong(getGuests()
.get(key));
if (time > lasttime)
// 超時
getGuests().remove(key);
}// end if (key != null)
}// end while (keys.hasMoreElements())
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
e.printStackTrace();
trace("error - " + e.toString());
}
}// end while (mobiles != null && mobiles.size() > 0)
trace("AutoCleanThread thread end...");
}
}
}
/**
* 通訊端口的客戶端限制管理器的抽象類
* 該類繼承自GuestManager類,增加了connect()、disconnect()等方法
*
* @author none
*
*/
public abstract class PortGuestManager extends GuestManager {
/**
* 連接
*
* @return 返回是否連接成功
*/
protected abstract boolean connect();
/**
* 斷開
*
* @return 返回是否斷開成功
*/
protected abstract boolean disconnect();
/**
* 是否已經(jīng)連接
*
* @return 返回端口是否已經(jīng)連接
*/
protected abstract boolean isConnected();
public long login() {
long guestid = -1L;
if (!isConnected())
connect();
if (isConnected())
guestid = super.login();
return guestid;
}
public boolean limit(long guestid) {
boolean flag = false;
if (isConnected())
flag = super.limit(guestid);
return flag;
}
public void logout(long guestid) {
super.logout(guestid);
Hashtable guests = getGuests();
if (guests != null)
if (guests.size() <= 0)
disconnect();
}
public boolean isLimit(long guestid) {
boolean flag = true;
if (isConnected())
flag = super.isLimit(guestid);
return flag;
}
}
/**
* 客戶限制管理器的抽象類
* 此抽象類實現(xiàn)了對客戶訪問的限制,當(dāng)一個客戶訪問該服務(wù)時,可以通過halt(long guestid)方法阻止其他客戶進(jìn)行
* 訪問,防止多個客戶同時訪問產(chǎn)生的沖突。例如:對通訊端口的訪問等。
*/
public abstract class GuestManager {
/**
* 時間:一分鐘
*/
protected static final long ONE_MINUTE = 60L * 1000L;
/**
* 時間:一小時
*/
protected static final long ONE_HOUR = 60L * ONE_MINUTE;
/**
* 自動清理客戶記錄的間隔時間
*/
private long cleanInterval;
/**
* 客戶記錄<客戶標(biāo)識,最近訪問時間>
*/
private Hashtable
/**
* 當(dāng)前限制的客戶
*/
private long limitGuest;
/**
* 自動清除過期客戶的線程
*/
private Thread autoCleanThread;
/**
* 客戶注冊
*
* @return 返回分配給客戶端的標(biāo)識,如果注冊失敗,返回-1
*/
public long login() {
long guestid = -1L;
// 增加客戶記錄
Hashtable
if (guests != null) {
guestid = System.currentTimeMillis();
guests.put("" + guestid, "" + guestid);
update(guestid);
// if (guests.size() == 1)
// connect();
}
return guestid;
}
/**
* 檢查客戶是否已經(jīng)注冊
*
* @param guestid
* 客戶標(biāo)識
* @return 如果客戶已經(jīng)注冊返回true,否則返回false
*/
public boolean isLogin(long guestid) {
boolean flag = false;
if (guestid > 0) {
Hashtable
if (guests != null)
flag = guests.containsKey("" + guestid);
if (flag)
update(guestid);
}// end if (guestid > 0)
return flag;
}
/**
* 注銷客戶
* 如果仍有其他客戶在使用此對象,則僅僅注銷guestid客戶,否則調(diào)用disconnect()方法關(guān)閉連接。
*
* @param guestid
* 客戶標(biāo)識
* @return 返回是否成功注銷
*/
public void logout(long guestid) {
Hashtable
if (guests != null) {
if (guestid > 0 && guests.containsKey("" + guestid)) {
guests.remove("" + guestid);
}// end if (guestid > 0 && getGuests().containsKey("" +
// guestid))
}// end if (guests != null)
}
/**
* 限制
* 如果某一客戶調(diào)用了該方法,那么其他客戶將無法訪問,直至該客戶調(diào)用resume()釋放。
*
* @param guestid
* 中斷標(biāo)識
* @return 返回是否成功中斷
*/
public boolean limit(long guestid) {
boolean flag = false;
if (isLogin(guestid)) {
update(guestid);
if (isLimit(guestid))
return flag;
limitGuest = guestid;
flag = true;
}// end if (isLogin(guestid))
return flag;
}
/**
* 釋放
*
* @param guestid
* 客戶標(biāo)識
* @return 返回是否釋放成功
*/
public boolean resume(long guestid) {
boolean flag = false;
if (isLogin(guestid)) {
update(guestid);
if (limitGuest == guestid) {
limitGuest = -1L;
}// end if(haltGuest == guestid)
flag = !isLimit();
}
return flag;
}
/**
* 是否限制其他客戶調(diào)用
*
* @return 返回是否限制其他客戶調(diào)用
*/
protected boolean isLimit() {
boolean flag = false;
if (limitGuest > 0) {
long lasttime = Long.parseLong((getGuests().get(
"" + limitGuest)));
if (lasttime > 0) {
// 如果10分鐘內(nèi)無響應(yīng),則注釋放該客戶的中斷
long time = System.currentTimeMillis() - 10L
* ONE_MINUTE;
if (time < lasttime)
flag = true;
else
limitGuest = -1;
}
}// end if(this.id <= 0)
return flag;
}
/**
* 該客戶是否被限制訪問
*
* @param haltId
* 客戶標(biāo)識
* @return 返回true表示禁止訪問,false表示可以訪問
*/ public boolean isLimit(long guestid) {
boolean flag = true;
if (isLogin(guestid)) {
update(guestid);
flag = isLimit();
if (flag) {
if (guestid > 0 && limitGuest == guestid)
flag = false;
}// end if(flag)
}
return flag;
}
/**
* 取得當(dāng)前限制客戶的標(biāo)識(該標(biāo)識是該管理器為客戶分配的一個標(biāo)識)
*
* @return 返回當(dāng)前限制客戶的標(biāo)識
*/
protected long getLimitGuest() {
return limitGuest;
}
/**
* 更新客戶最近使用時間
*
* @param guestid
* 客戶標(biāo)識
*/
protected void update(long guestid) {
runThread();
Hashtable
if (guests != null && guests.containsKey("" + guestid))
guests.put("" + guestid, ""
+ System.currentTimeMillis());
}
/**
* 運行監(jiān)聽線程
*/
protected void runThread() {
// 客戶自動清理線程
if (autoCleanThread != null && !autoCleanThread.isAlive())
autoCleanThread = null;
if (autoCleanThread == null) {
autoCleanThread = new AutoCleanThread();
autoCleanThread.start();
}// end if (autoCleanThread == null)
}
/**
* 設(shè)置自動清理客戶記錄的間隔時間
*
* @param time
* 間隔時間(毫秒)
*/
public void setCleanInterval(long time) {
if (time > 0)
cleanInterval = time;
}
/**
* 取得自動清理客戶記錄的間隔時間
*
* @return 返回自動清理客戶記錄的間隔時間(毫秒)
*/
public long getCleanInterval() {
return cleanInterval;
}
/**
* 取得客戶記錄
*
* @return 返回客戶記錄。格式為<客戶標(biāo)識,最近訪問時間>
*/
protected Hashtable
if (guests == null)
guests = new Hashtable
return guests;
}
/**
* 輸出錯誤信息
*
* @param err
*/
public abstract void trace(String err);
/**
* 自動清除超時的客戶端的線程
*
*/
private class AutoCleanThread extends Thread {
public void run() {
trace("AutoCleanThread thread start runing...");
long interval = ONE_HOUR / 4L;
if (getCleanInterval() > 0)
interval = getCleanInterval();
while (autoCleanThread == this && getGuests().size() > 0) {
long time = System.currentTimeMillis()
- ONE_HOUR / 2L;
Enumeration> keys = getGuests().keys();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
if (key != null) {
long lasttime = Long.parseLong(getGuests()
.get(key));
if (time > lasttime)
// 超時
getGuests().remove(key);
}// end if (key != null)
}// end while (keys.hasMoreElements())
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
e.printStackTrace();
trace("error - " + e.toString());
}
}// end while (mobiles != null && mobiles.size() > 0)
trace("AutoCleanThread thread end...");
}
}
}
/**
* 通訊端口的客戶端限制管理器的抽象類
* 該類繼承自GuestManager類,增加了connect()、disconnect()等方法
*
* @author none
*
*/
public abstract class PortGuestManager extends GuestManager {
/**
* 連接
*
* @return 返回是否連接成功
*/
protected abstract boolean connect();
/**
* 斷開
*
* @return 返回是否斷開成功
*/
protected abstract boolean disconnect();
/**
* 是否已經(jīng)連接
*
* @return 返回端口是否已經(jīng)連接
*/
protected abstract boolean isConnected();
public long login() {
long guestid = -1L;
if (!isConnected())
connect();
if (isConnected())
guestid = super.login();
return guestid;
}
public boolean limit(long guestid) {
boolean flag = false;
if (isConnected())
flag = super.limit(guestid);
return flag;
}
public void logout(long guestid) {
super.logout(guestid);
Hashtable
if (guests != null)
if (guests.size() <= 0)
disconnect();
}
public boolean isLimit(long guestid) {
boolean flag = true;
if (isConnected())
flag = super.isLimit(guestid);
return flag;
}
}