import com.hwqh.huawenstockuser.common.ConstantUtil;
import com.hwqh.huawenstockuser.config.MyConfiguration;
import com.hwqh.huawenstockuser.entity.model.LinkAccount;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import redis.clients.jedis.*;
import redis.clients.jedis.exceptions.JedisException;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* JedisPool工具類
* 加載配置文件,配置連接池的參數
* 提供獲取連接的方法
*/
public class JedisPoolUtils {
private static final Logger logger = LoggerFactory.getLogger(JedisPoolUtils.class);
public static JedisPool jedisPool;
static {
//獲取數據,設置到JedisPoolConfig中
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(MyConfiguration.create().getInt("spring.redis.jedis.pool.max-active"));
config.setMaxIdle(MyConfiguration.create().getInt("spring.redis.jedis.pool.max-idle"));
String string = MyConfiguration.create().getString("spring.redis.password");
if (StringUtils.isEmpty(string)){
jedisPool = new JedisPool(config, MyConfiguration.create().getString("spring.redis.host"), MyConfiguration.create().getInt("spring.redis.port"));
}else{
jedisPool = new JedisPool(config, MyConfiguration.create().getString("spring.redis.host"), MyConfiguration.create().getInt("spring.redis.port"),
MyConfiguration.create().getInt("spring.redis.timeout"),MyConfiguration.create().getString("spring.redis.password"));
}
/**
* 獲取分佈式鎖
*
* @param lockName
* 競爭獲取鎖key
* @param acquireTimeoutInMS
* 獲取鎖超時時間
* @param lockTimeoutInMS
* 鎖的超時時間
* @return 獲取鎖標識
*/
public static String acquireLockWithTimeout(String lockName,
long acquireTimeoutInMS, long lockTimeoutInMS) {
Jedis conn = null;
boolean broken = false;
String retIdentifier = null;
try {
conn = jedisPool.getResource();
String identifier = UUID.randomUUID().toString();
String lockKey = "lock:" + lockName;
int lockExpire = (int) (lockTimeoutInMS / 1000);
long end = System.currentTimeMillis() + acquireTimeoutInMS;
while (System.currentTimeMillis() < end) {
if (conn.setnx(lockKey, identifier) == 1) {
conn.expire(lockKey, lockExpire);
retIdentifier = identifier;
return retIdentifier;
}
if (conn.ttl(lockKey) == -1) {
conn.expire(lockKey, lockExpire);
}
try {
Thread.sleep(10);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
} catch (JedisException je) {
if (conn != null) {
broken = true;
jedisPool.returnBrokenResource(conn);
}
} finally {
if (conn != null && !broken) {
jedisPool.returnResource(conn);
}
}
return retIdentifier;
}
/**
* 釋放鎖
* @param lockName 競爭獲取鎖key
* @param identifier 釋放鎖標識
* @return
*/
public static boolean releaseLock(String lockName, String identifier) {
Jedis conn = null;
boolean broken = false;
String lockKey = "lock:" + lockName;
boolean retFlag = false;
try {
conn = jedisPool.getResource();
while (true) {
conn.watch(lockKey);
if (identifier.equals(conn.get(lockKey))) {
Transaction trans = conn.multi();
trans.del(lockKey);
List<Object> results = trans.exec();
if (results == null) {
continue;
}
retFlag = true;
}
conn.unwatch();
break;
}
} catch (JedisException je) {
if (conn != null) {
broken = true;
jedisPool.returnBrokenResource(conn);
}
} finally {
if (conn != null && !broken) {
jedisPool.returnResource(conn);
}
}
return retFlag;
}
public static void main(String[] args) {
for(int i = 0 ; i < 20; i ++){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Long s = System.currentTimeMillis();
String key = "K_1000";
String kIdentifier = acquireLockWithTimeout(key,1000L,1000L);
if(kIdentifier == null){
System.err.println("獲取鎖失敗");
return;
} else {
System.err.println("獲取鎖花費:"+(System.currentTimeMillis() - s));
}
try {
// 模擬業務代碼執行塊
Thread.sleep(100L);
} catch (Exception e){
e.printStackTrace();
}
System.err.println("執行業務代碼(+100):"+ (System.currentTimeMillis()-s));
//釋放鎖
releaseLock(key,kIdentifier);
System.err.println("End--------------------------------- 釋放鎖總花費時間:"+(System.currentTimeMillis()-s));
}
});
thread.start();
try {
// 測試併發10毫秒
Thread.sleep(10L);
} catch (Exception e){
e.printStackTrace();
}
}
}
}
基於Redis實現分佈式鎖-java工具類
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.