基於Redis實現分佈式鎖-java工具類

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();
            }

        }


    }


}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章