分布式锁的简单实现代码:
/** * 分布式锁的简单实现代码 * Created by liuyang on 2017/4/20. */ public class
DistributedLock { private final JedisPool jedisPool; public DistributedLock
(JedisPool jedisPool) {this.jedisPool = jedisPool; } /** * 加锁 * @param lockName
锁的key * @param acquireTimeout 获取超时时间 * @param timeout 锁的超时时间 * @return 锁标识 */
public String lockWithTimeout(String lockName, long acquireTimeout, long
timeout) { Jedis conn =null; String retIdentifier = null; try { // 获取连接 conn =
jedisPool.getResource();// 随机生成一个value String identifier =
UUID.randomUUID().toString();// 锁名,即key值 String lockKey = "lock:" + lockName;
// 超时时间,上锁后超过此时间则自动释放锁 int lockExpire = (int) (timeout / 1000); //
获取锁的超时时间,超过这个时间则放弃获取锁 long end = System.currentTimeMillis() + acquireTimeout;
while (System.currentTimeMillis() < end) { if (conn.setnx(lockKey, identifier)
==1) { conn.expire(lockKey, lockExpire); // 返回value值,用于释放锁时间确认 retIdentifier =
identifier;return retIdentifier; } // 返回-1代表key没有设置超时时间,为key设置一个超时时间 if
(conn.ttl(lockKey) == -1) { conn.expire(lockKey, lockExpire); } try {
Thread.sleep(10); } catch (InterruptedException e) {
Thread.currentThread().interrupt(); } } }catch (JedisException e) {
e.printStackTrace(); }finally { if (conn != null) { conn.close(); } } return
retIdentifier; }/** * 释放锁 * @param lockName 锁的key * @param identifier 释放锁的标识 *
@return */ public boolean releaseLock(String lockName, String identifier) {
Jedis conn =null; String lockKey = "lock:" + lockName; boolean retFlag = false;
try { conn = jedisPool.getResource(); while (true) { // 监视lock,准备开始事务
conn.watch(lockKey);// 通过前面返回的value值判断是不是该锁,若是该锁,则删除,释放锁 if
(identifier.equals(conn.get(lockKey))) { Transaction transaction =
conn.multi(); transaction.del(lockKey); List<Object> results =
transaction.exec();if (results == null) { continue; } retFlag = true; }
conn.unwatch();break; } } catch (JedisException e) { e.printStackTrace(); }
finally { if (conn != null) { conn.close(); } } return retFlag; } }
*

测试刚才实现的分布式锁

例子中使用50个线程模拟秒杀一个商品,使用–运算符来实现商品减少,从结果有序性就可以看出是否为加锁状态。

模拟秒杀服务,在其中配置了jedis线程池,在初始化的时候传给分布式锁,供其使用。
/** * Created by liuyang on 2017/4/20. */ public class Service { private static
JedisPool pool =null; private DistributedLock lock = new DistributedLock(pool);
int n = 500; static { JedisPoolConfig config = new JedisPoolConfig(); // 设置最大连接数
config.setMaxTotal(200); // 设置最大空闲数 config.setMaxIdle(8); // 设置最大等待时间
config.setMaxWaitMillis(1000 * 100); //
在borrow一个jedis实例时,是否需要验证,若为true,则所有jedis实例均是可用的 config.setTestOnBorrow(true);
pool =new JedisPool(config, "127.0.0.1", 6379, 3000); } public void seckill() {
// 返回锁的value值,供释放锁时候进行判断 String identifier = lock.lockWithTimeout("resource",
5000, 1000); System.out.println(Thread.currentThread().getName() + "获得了锁");
System.out.println(--n); lock.releaseLock("resource", identifier); } }
模拟线程进行秒杀服务:
public class ThreadA extends Thread { private Service service; public ThreadA
(Service service) {this.service = service; } @Override public void run() {
service.seckill(); } }public class Test { public static void main(String[]
args) { Service service =new Service(); for (int i = 0; i < 50; i++) { ThreadA
threadA =new ThreadA(service); threadA.start(); } } }
结果如下,结果为有序的:



若注释掉使用锁的部分:
public void seckill() { // 返回锁的value值,供释放锁时候进行判断 //String indentifier = lock
.lockWithTimeout("resource", 5000, 1000); System.out.println(Thread
.currentThread().getName() + "获得了锁"); System.out.println(--n); //lock
.releaseLock("resource", indentifier); }
从结果可以看出,有一些是异步进行的:


友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信