面試常常遇到寫乙個搶購例項,或者講講搶購實現想法,然後總是講不明白,因為目前工作沒做搶購這一塊兒。
但是這個想法今天終於搞明白了,其中也參照了一些大佬的做法。
junit測試類:
log log = logfactory.getlog(getclass());
@autowired
private redistemplateredistemplate;
@test
public void testsys() throws exception
}
threadb類:
private msservice service;
private redistemplateredistemplate;
private string key;
public threadb(msservice service,redistemplateredistemplate,string key)
@override
public void run() catch (interruptedexception e) catch (exception e)
}
msservice類:
log log = logfactory.getlog(getclass());
/***
* 搶購**
* @param redistemplate
* @param key pronum 首先用客戶端設定數量
* @return
* @throws interruptedexception
*/public boolean seckill(redistemplateredistemplate, string key) throws exception else
log.info("++++++++++++++++++++++++++++++++++++++參加了搶購");
return true;
} } catch (interruptedexception e) finally
return false;
}
redislock類:
public class redislock
/*** detailed constructor with default lock expiration of 60000 msecs.**/
public redislock(redistemplateredistemplate, string lockkey, int timeoutmsecs)
/*** detailed constructor.**/
public redislock(redistemplateredistemplate, string lockkey, int timeoutmsecs, int expiremsecs)
/*** @return lock key
*/public string getlockkey()
public string get(final string key)
return serializer.deserialize(data);
}});
} catch (exception e) ", key);
}return obj != null ? obj.tostring() : null;
}public string set(final string key,final string value)
});} catch (exception e) ", key);
}return obj != null ? obj.tostring() : null;
}public boolean setnx(final string key, final string value)
});} catch (exception e) ", key);
}return obj != null ? (boolean) obj : false;
}private string getset(final string key, final string value)
});} catch (exception e) ", key);
}return obj != null ? (string) obj : null;
}/**
* 獲得 lock. 實現思路: 主要是使用了redis 的setnx命令,快取了鎖. reids快取的key是鎖的key,所有的共享,
* value是鎖的到期時間(注意:這裡把過期時間放在value了,沒有時間上設定其超時時間) 執行過程:
* 1.通過setnx嘗試設定某個key的值,成功(當前沒有這個鎖)則返回,成功獲得鎖
* 2.鎖已經存在則獲取鎖的到期時間,和當前時間比較,超時的話,則設定新的值
** @return true if lock is acquired, false acquire timeouted
* @throws interruptedexception
* in case of thread interruption
*/public synchronized boolean lock() throws interruptedexception
string currentvaluestr = this.get(lockkey); // redis裡的時間
if (currentvaluestr != null && long.parselong(currentvaluestr) < system.currenttimemillis())
}timeout -= default_acquiry_resolution_millis;
/** 延遲100 毫秒, 這裡使用隨機時間可能會好一點,可以防止飢餓程序的出現,即,當同時到達多個程序,
* 只會有乙個程序獲得鎖,其他的都用同樣的頻率進行嘗試,後面有來了一些進行,也以同樣的頻率申請鎖,這將可能導致前面來的鎖得不到滿足.
* 使用隨機的等待時間可以一定程度上保證公平性
*/thread.sleep(default_acquiry_resolution_millis);
}return false;
}/**
* acqurired lock release.
*/public synchronized void unlock()
}
至此基於redis的搶購簡單實現。大佬如果覺得有不妥的地方請指正,小弟也可以進步一點點。
java 基於redis實現分布式鎖
前幾天,被問到併發操作如何解決一條資料被請求多次處理事件的技術解決方案,當時只有一點印象,利用鎖機制,但是讀寫鎖對於分布式部署的專案來說是無法實現的。事後去檢視博友們提供的技術方案。決定基於redis自己嘗試寫乙個分布式鎖來實現多執行緒操作。類似乙個秒殺功能吧,這裡有個問題就是其實並不是執行緒搶到了...
java實現並查集
並查集是根據這篇博文學習的,寫得很不錯 下面是實現 public class unionfindset count n 合併p,q所在集合 param p param q public void union int p,int q if size rootp size rootq else coun...
基於java的websocket實現
基於tomcat的websocket實現中,如果會針對乙個使用者高頻的傳送訊息的情況下,websocket自帶的非同步傳送其實一點卵用都沒有,所以,沒辦法,自己控制websocket的併發傳送嘍,不多說,直接貼 1.基礎的websocket快取物件,這個玩意兒每乙個使用者進來都會生成乙個 publi...