import
java.util.Random;
import
redis.clients.jedis.Jedis;
import
redis.clients.jedis.JedisPool;
import
redis.clients.jedis.Transaction;
public
class
RedisLock {
public
static
final
String LOCKED =
"TRUE"
;
public
static
final
long
ONE_MILLI_NANOS = 1000000L;
public
static
final
long
DEFAULT_TIME_OUT =
3000
;
public
static
JedisPool pool;
public
static
final
Random r =
new
Random();
public
static
final
int
EXPIRE =
5
*
60
;
private
Jedis jedis;
private
String key;
private
boolean
locked =
false
;
public
RedisLock(String key) {
this
.key = key;
this
.jedis=
new
Jedis(
"127.0.0.1"
,
6379
,
60000
);
}
/**
* 通过jedis.setnx实现锁
* @param timeout
* @return
*/
public
boolean
lock(
long
timeout) {
long
nano = System.nanoTime();
timeout *= ONE_MILLI_NANOS;
try
{
while
((System.nanoTime() - nano) < timeout) {
if
(jedis.setnx(key, LOCKED) ==
1
) {
jedis.expire(key, EXPIRE);
locked =
true
;
return
locked;
}
Thread.sleep(
3
, r.nextInt(
500
));
}
}
catch
(Exception e) {
}
return
false
;
}
/**
* 事务和管道都是异步模式。在事务和管道中不能同步查询结果,因此下面 t.getSet(key, LOCKED);只能被一个线程查询
* 否则线程获取不到
* @param timeout
* @return
*/
public
boolean
lock_2(
long
timeout) {
long
nano = System.nanoTime();
timeout *= ONE_MILLI_NANOS;
try
{
while
((System.nanoTime() - nano) < timeout) {
Transaction t = jedis.multi();
t.getSet(key, LOCKED);
t.expire(key, EXPIRE);
String ret = (String) t.exec().get(
0
);
System.out.println(Thread.currentThread()+
" ========== "
+ret);
if
(ret!=
null
&&ret.equalsIgnoreCase(
"TRUE"
))
return
true
;
Thread.sleep(
3
, r.nextInt(
500
));
}
}
catch
(Exception e) {
}
return
false
;
}
public
boolean
lock_3(
long
timeout) {
long
nano = System.nanoTime();
timeout *= ONE_MILLI_NANOS;
try
{
while
((System.nanoTime() - nano) < timeout) {
jedis.watch(key);
String value = jedis.get(key);
if
(value ==
null
|| value.equals(
"UNLOCK"
)) {
Transaction t = jedis.multi();
t.setex(key, EXPIRE, LOCKED);
if
(t.exec() !=
null
) {
return
true
;
}
}
jedis.unwatch();
Thread.sleep(
3
, r.nextInt(
500
));
}
}
catch
(Exception e) {
}
return
false
;
}
public
boolean
lock() {
return
lock(DEFAULT_TIME_OUT);
}
public
void
unlock() {
if
(locked)
jedis.del(key);
}
}