测试样例:
package com...redis.redisSuo.demo; import com...redis.RedisPoolUtils; import com...redis.redisSuo.JedisSuoUtils; import redis.clients.jedis.Jedis; import...RecordSet; import...SQL; import java.util.UUID; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class demo { private static RedisPoolUtils redisPoolUtils = new RedisPoolUtils(); private final static String key = "keys"; private static final int Thread_num = 20; private static final CyclicBarrier cb = new CyclicBarrier(Thread_num); public static void sendThreads() throws InterruptedException { Thread [] threads = new Thread[Thread_num]; for(int i=0;i<Thread_num;i++){ Thread thread = new Thread(new Runnable() { @Override public void run() { try { cb.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } String res = getKey(key); System.out.println(res); } }); threads [i] = thread; thread.start(); } for(Thread thread : threads){ thread.join(); } System.out.println("执行结束======"); } public static void main(String[] args) throws InterruptedException { sendThreads(); } public static String getKey(String key) { String redisKey = key; String lockKey = "locks:"+key; String lockRequestId = UUID.randomUUID().toString(); System.out.println(Thread.currentThread().getName() + "lockRequestId--->"+lockRequestId); Jedis jedis = redisPoolUtils.getResource(); try { while (true) { //获取分布式锁,时间设为3秒 boolean getLock = JedisSuoUtils.tryGetDistributedLock(jedis, lockKey, lockRequestId, 3000); System.out.println(Thread.currentThread().getName() + "获取锁的结果:--->" + getLock); if (getLock) { int count = 1; String st_fj_id = key; String updateSql = "update dang_fj set count = count-? where st_fj_id = ? and count>=1"; Object[] updateObject = new Object[] {count,st_fj_id}; RecordSet updateRs = SQL.execute(updateSql,updateObject); int number = updateRs.TOTAL_RECORD_COUNT; //影响行数 System.out.println("数据库影响行数:"+number); if(number==1){ String counts = ""; String selectSql = "select * from dang_fj where st_fj_id = ?"; Object[] selectObject = new Object[]{key}; RecordSet selectRs = SQL.execute(selectSql, selectObject); while (selectRs.next()) { counts = selectRs.getString("COUNT"); } System.out.println("数据库剩余---->"+counts); String redisRs = jedis.setex(redisKey,60*60,counts); System.out.println("更改redis结果--->:"+redisRs); return Thread.currentThread().getName() + "去数据库拿结果~~~~:" + counts; }else { return Thread.currentThread().getName() + "更改数据库失败~~~~"; } } try { Thread.sleep(1000); } catch (InterruptedException ignored) { } } } catch (Exception e) { e.printStackTrace(); }finally { //不论结果如何,一定要释放锁 boolean releaseLock = JedisSuoUtils.releaseDistributedLock(jedis, lockKey, lockRequestId); jedis.close(); System.out.println(Thread.currentThread().getName()+"释放锁的结果:--->"+releaseLock); } return Thread.currentThread().getName()+"最后结果lockRequestId--->"+lockRequestId; } }
加锁解锁 工具类:
package com...redis.redisSuo; import redis.clients.jedis.Jedis; import java.util.Collections; /** * @author * @date 2019/8/10 */ public class JedisSuoUtils { private static final String LOCK_SUCCESS = "OK"; private static final String SET_IF_NOT_EXIST = "NX"; private static final String SET_WITH_EXPIRE_TIME = "PX"; private static final Long RELEASE_SUCCESS = 1L; /** * 尝试获取分布式锁 * * @param jedis Redis客户端 * @param lockKey 锁 * @param requestId 请求标识 * @param expireTime 超期时间, 单位毫秒 * @return 是否获取成功 */ public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) { String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); return LOCK_SUCCESS.equals(result); } /** * 释放分布式锁 * * @param jedis Redis客户端 * @param lockKey 锁 * @param requestId 请求标识 * @return 是否释放成功 */ public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) { String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); return result.equals(RELEASE_SUCCESS); } }
锁续命小demo:
// 加锁后开始调用方法 :开个子线程,原来时间30,每隔30/3,重置为30 LockService.renewLock(lock.intern(),driverId,30); 接口: package com....service; public interface LockService { /** * 续约 * @param key * @param value * @param time */ public void Lock(String key , String value , int time); 实现: package com.....impl; import com.....LockService; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.util.concurrent.TimeUnit; @Service public class LockServiceImpl implements LockService { @Autowired private RedisTemplate<String, String> redisTemplate; @Override @Async public void Lock(String key, String value, int time) { String v = redisTemplate.opsForValue().get(key); if (StringUtils.isNotBlank(v) && v.equals(value)){ System.out.println("进入续命操作... "+key+" "+value); int sleepTime = time / 3; try { Thread.sleep(sleepTime * 1000); } catch (InterruptedException e) { e.printStackTrace(); } redisTemplate.expire(key,time,TimeUnit.SECONDS); Lock(key,value,time); } } }