/*
 * Copyright (c) 2014-2015 ,fangzy (zyuanf@gmail.com)
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package org.reindeer.redis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;

/**
 * redis实现的分布式锁
 * Created by fzy on 2014/9/1.
 */
public final class JLock {

    private static final String LOCK = "redis:lock:%s";
    private static final int EXPIRE = 1200;
    private static final Logger LOGGER = LoggerFactory.getLogger(JLock.class);

    private JLock() {

    }

    /**
     * 获得锁,未取得时一直阻塞
     *
     * @param id
     */
    public static void getLock(String id) {
        getLock(id, 0);
    }

    /**
     * 获得锁,超时退出
     *
     * @param id
     * @param timeout 超时时间(ms)
     * @return
     */
    public static boolean getLock(String id, int timeout) {
        Jedis jedis = JedisProxy.create();
        long lock = 0;
        long start = System.currentTimeMillis();
        while (lock != 1) {
            long now = System.currentTimeMillis();
            //判断超时
            if (timeout > 0 && now > start + timeout) {
                return false;
            }
            long timestamp = now + EXPIRE + 1;
            String key = String.format(LOCK, id);
            lock = jedis.setnx(key, String.valueOf(timestamp));
            if (lock == 1) {
                jedis.expire(key, EXPIRE);
                LOGGER.debug("setnx");
            } else {
                sleep();
            }
        }
        return true;
    }

    private static void sleep() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            LOGGER.error("An unexpected error occurred.", e);
        }
    }

    /**
     * 释放锁
     *
     * @param id
     */
    public static void releaseLock(String id) {
        Jedis jedis = JedisProxy.create();
        String key = String.format(LOCK, id);
        String val = jedis.get(key);
        if (val == null) {
            return;
        }
        long lastLockTime = Long.parseLong(val);
        if (lastLockTime > System.currentTimeMillis() / 1000) {
            jedis.del(key);
        }
    }
}

@@ -840,24 +840,67 @@
 ss JLock %7B%0A%0A
+    public static final int EXPIRE = 1200;%0A
     private 
@@ -947,52 +947,8 @@
 s%22;%0A
-    private static final int EXPIRE = 1200;%0A
     
@@ -1080,16 +1080,29 @@
 %E6%9C%AA%E5%8F%96%E5%BE%97%E6%97%B6%E4%B8%80%E7%9B%B4%E9%98%BB%E5%A1%9E
+,%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%E9%BB%98%E8%AE%A41200s;
 %0A     *%0A
@@ -1348,19 +1348,20 @@
 ing id, 
-int
+long
  timeout
@@ -1471,32 +1471,101 @@
 ntTimeMillis();%0A
+        long pexpire = timeout %3E 0 ? (long) timeout : EXPIRE * 1000;%0A
         while (l
@@ -1958,16 +1958,17 @@
   jedis.
+p
 expire(k
@@ -1971,22 +1971,23 @@
 re(key, 
-EXPIRE
+pexpire
 );%0A     
@@ -2072,32 +2072,32 @@
 ;%0A            %7D%0A
-
         %7D%0A      
@@ -2114,24 +2114,485 @@
 rue;%0A    %7D%0A%0A
+    /**%0A     * %E6%A3%80%E6%9F%A5%E9%94%81%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8,%E7%AB%8B%E5%88%BB%E8%BF%94%E5%9B%9E%0A     *%0A     * @param id%0A     * @param timeout%0A     * @return%0A     */%0A    public static boolean checkLock(String id, long timeout) %7B%0A        Jedis jedis = JedisProxy.create();%0A        String key = String.format(LOCK, id);%0A        long exists = jedis.setnx(key, String.valueOf(System.currentTimeMillis()));%0A        if (exists == 0) %7B%0A            return false;%0A        %7D%0A        jedis.pexpire(key, timeout);%0A        return true;%0A    %7D%0A%0A
     private 

update lock