直接貼上代碼
/** * @param subKey set Key name * @param timeout get lock timeout,if not get, * @param unit time unit * @param sValue * @return */ public static boolean tryLock(String subKey, String sValue,long timeout, TimeUnit unit) { String key = subKey; Jedis jedis = null;try {jedis = getResource(); if (jedis == null) {return Boolean.FALSE;}long nano = System.nanoTime();do {logger.debug("try lock key: " + key);Long i = jedis.setnx(key, sValue); //此處可能出現死結(執行setnx後,redis crash ,key一直存在)if (i == 1) {jedis.expire(key, 5);//鎖失效時間5秒logger.debug("get lock, key: " + key + " , expire in "+ 2 + " seconds.");return Boolean.TRUE;} //解決出現死結問題 可最佳化為 getset方式 重新設定值// key存在, 擷取key的內容值, 值為nanotime 納秒 ,當前的時間 - key的值>鎖 鎖定時間,此時可擷取鎖String value = jedis.get(key);if (StringUtils.isNotBlank(value) && !"nil".equalsIgnoreCase(value)&&(System.nanoTime()-Long.valueOf(value))>TimeUnit.SECONDS.toNanos(5)) {set(key, value, 5); //設定key 5秒到期 自動釋放return Boolean.TRUE;}if (timeout == 0) { // 取不到鎖時,不等待,直接返回.break;}Thread.sleep((int)(50*Math.random()+50));// 等待50- 100毫秒 避免不同線程競爭時間相同} while ((System.nanoTime() - nano) < unit.toNanos(timeout));// 取不到鎖時等待,直到timeoutif (logger.isInfoEnabled()) {String desc = jedis.get(key);logger.debug("key: " + key+ " locked by another business:" + desc);}return Boolean.FALSE;}catch (Exception e) {logger.error(e.getMessage(), e);} finally {returnResource(jedis);//釋放串連} return Boolean.FALSE; } /** 擷取key對應值,對比值內容, 相同則刪除,釋放鎖,避免刪除其他線程已經擷取的鎖 * @param subKey * @param sValue */public static boolean unLock(String subKey,String sValue) {String key = subKey;Jedis jedis = null;try {jedis = getResource(); if (jedis == null) {return false;}String str = jedis.get(subKey);if (str.equals(sValue)) {jedis.del(key);logger.debug("release lock, keys :" + key);return true;}else {logger.debug("the key is not exist,key : " + key);}} catch (Exception e) {logger.error(e.getMessage(), e);} finally {returnResource(jedis);//釋放串連}return false;}public static void main(String args[]){String sValue = String.valueOf(System.nanoTime());String subKey = "productId";try {// 5000毫秒 boolean lock = tryLock(subKey, sValue, 5000, TimeUnit.MILLISECONDS);if (lock) {//do job 相關商務邏輯}} catch (Exception e) {e.printStackTrace();}finally{unLock(subKey, sValue);}}