類:
import com.hoolai.fastaccess.common.log.Log;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
/**
* Redis distributed lock implementation.
*
* @author Alois Belaska <[email protected]>
*/
public class JedisLock {
Jedis jedis;
JedisPool jedisPool;
/**
* Lock key path.
*/
String lockKey;
/**
* Lock expiration in seconds.
*/
int expireMsecs = 60 ;
/**
* Acquire timeout in seconds.
*/
int timeoutMsecs = 0;
boolean locked = false;
/**
* Detailed constructor.
*
* @param jedis
* @param lockKey
* lock key (ex. account:1, ...)
* @param timeoutSecs
* acquire timeout in seconds (default: 0 secs)
* @param expireMsecs
* lock expiration in seconds (default: 60 secs)
*/
public JedisLock(JedisPool jedisPool, String lockKey, int timeoutMsecs, int expireMsecs) {
this.jedisPool = jedisPool;
this.jedis = jedisPool.getResource();
this.lockKey = lockKey;
this.timeoutMsecs = timeoutMsecs;
this.expireMsecs = expireMsecs;
if(timeoutMsecs > expireMsecs){
throw new IllegalArgumentException("expireMsecs 必須大於 timeoutMsecs; expireMsecs:"+expireMsecs+",timeoutMsecs:"+timeoutMsecs);
}
}
/**
* @return lock key
*/
public String getLockKey() {
return lockKey;
}
/**
* Acquire lock.
*
* @param jedis
* @return true if lock is acquired, false acquire timeouted
* @throws InterruptedException
* in case of thread interruption
*/
public synchronized boolean acquire() throws InterruptedException {
try {
if(jedis.exists(lockKey)&&jedis.ttl(lockKey)==-1){
String expires = jedis.get(lockKey);
if(expires!=null){
//只有未過期 才設置過期時間
if(Long.valueOf(expires) > System.currentTimeMillis()/1000){
jedis.expireAt(lockKey,Long.valueOf(expires));
}
}
}
int timeout = timeoutMsecs*1000;
int count= 0;
while (true) {
if(++count>2000){
break;
}
Long expires = System.currentTimeMillis() / 1000 + expireMsecs + (expireMsecs>0 ? 0 : 1);
String expiresStr = String.valueOf(expires);
if (jedis.setnx(lockKey, expiresStr) == 1) {
jedis.expireAt(lockKey, expires);
locked = true;
return true;
}
timeout -= 100;
if (timeout < 0) {
return false;
}
Thread.sleep(100);
}
return false;
} catch (Exception e) {
e.printStackTrace();
Log.error("jedis acquire failed",e);
return false;
}
}
/**
* Acqurired lock release.
*/
public synchronized void release() {
if (locked) {
jedis.del(lockKey);
locked = false;
}
if(jedis!=null){
jedisPool.returnResource(jedis);
}
}
}
用法:
package com.hoolai.fastaccess.web.domain.task;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
import com.hoolai.fastaccess.common.jedislock.JedisLock;
import com.hoolai.fastaccess.common.jedislock.JedisLockFactory;
import com.hoolai.fastaccess.common.log.Log;
import com.hoolai.fastaccess.web.dao.mybatis.mapper.charge.ChargeOrderDao;
import com.hoolai.fastaccess.web.dao.mybatis.mapper.logs.StatisticsLogDao;
import com.hoolai.fastaccess.web.dao.mybatis.mapper.web.CollectChargeDao;
import com.hoolai.fastaccess.web.dao.mybatis.mapper.web.CollectOrderDao;
import com.hoolai.fastaccess.web.dao.mybatis.vo.CollectOrder;
@Component
public class CollectOrderTask {
private final String KEYSTR = "collect_order_key";
@Resource
private JedisLockFactory jedisLockFactory;
@Resource
private StatisticsLogDao statisticsLogDao;
@Resource
private ChargeOrderDao chargeOrderDao;
@Resource
private CollectChargeDao collectChargeDao;
@Resource
private CollectOrderDao collectOrderDao;
public void collect_order() {
JedisLock jedisLock = null;
try {
jedisLock = jedisLockFactory.create(KEYSTR, 0, 20);
boolean acquire = jedisLock.acquire();
if (acquire) {
collectOrderDao.delCollectOrder();
List<CollectOrder> collectOrderList = chargeOrderDao
.getCollectOrder();
for (CollectOrder collectOrder : collectOrderList) {
collectOrderDao.insert(collectOrder);
}
}
} catch (InterruptedException e) {
Log.error("create key_str:" + KEYSTR + " failed.", e);
return;
} catch (Exception e) {
Log.error("create key_str:" + KEYSTR + " failed.", e);
} finally {
if (jedisLock != null) {
try {
jedisLock.release();
} catch (Exception e) {
Log.error("jedisLock.release() failed", e);
}
}
}
}
}