当然分布式并不适用
使用示例
获取锁组
/**
*
* lockGroupName 锁组名称
* 1000l 该锁组最大包含锁数量
* 5000l 当超过最大锁数量时,被清理锁的持有时间最大值,单位ms
*/
LockUtils lockUtils = LockUtilsFactory.genLockUtils("lockGroupName", 1000l, 5000l);
//加锁,key=关键字
lockUtils.lock(key);
try{
}finally {
//解除锁
lockUtils.unLock(key);
}
这里锁组的意思是表示不同的业务场景。
比如可能在:绑定手机号、下单,都想按手机号来加锁,如果共用一个锁组,那么显然按相同的手机号会争用同一个锁,不同的业务争用同一个锁是不合理的。而且每种业务的并发率以及处理时间都是不一样的,所以需要不同的数量配置。
相同锁组名只会取到唯一的锁组
package com.coolsn.modules.tb.lockTools;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class LockUtilsFactory {
/**
* 锁组
*/
private static Map<String, LockUtils> lockUtilsMap = new HashMap<String,LockUtils>();
/**
* 锁组锁
*/
private static LockUtils flockLockUtils = LockUtils.init(1000l, 1*24*60*60*1000l);
/**
*
* 获取锁组
*
* @param lockName 锁名称
* @param lockMax 锁最大数
* @param nowToDis 锁存活时间
* @return
*/
public static LockUtils genLockUtils(String lockName,long lockMax,Long nowToDis) {
LockUtils lockUtils = null;
try {
flockLockUtils.lock(lockName);
if (lockUtilsMap.containsKey(lockName)) {
lockUtils = lockUtilsMap.get(lockName);
}
lockUtils = LockUtils.init(lockMax, nowToDis);
lockUtilsMap.put(lockName, lockUtils);
} finally {
flockLockUtils.unLock(lockName);
}
return lockUtils;
}
public static void main(String[] args) throws InterruptedException {
//实验:组与组之间不影响,组内影响
//第一组
new Thread(()->{
LockUtils lockUtils = genLockUtils("first",1000l, 5000l);
int i = 0;
while (i<10000) {
try {
Thread.sleep(800l);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("1=========>"+i);
int ik = i;
new Thread(() -> {
String key = String.valueOf(" "+1+"-"+100000+ik);
lockUtils.lock(key);
try {
System.out.println(new Date() + key+" 1 s ");
try {
Thread.sleep(1000);
} catch (Exception ex) {
}
System.out.println(new Date() + key+" 1 e ");
} finally {
lockUtils.unLock(key);
}
}).start();
new Thread(() -> {
String key = String.valueOf(" "+1+"-"+100000+ik);
lockUtils.lock(key);
try {
System.out.println(new Date() + key+" 2 s ");
try {
Thread.sleep(1000);
} catch (Exception ex) {
}
System.out.println(new Date() + key+" 2 e ");
} finally {
lockUtils.unLock(key);
}
}).start();
i++;
}
}).start();
//第二组
new Thread(()->{
LockUtils lockUtils2 = genLockUtils("scend",1000l, 5000l);
int j = 0;
while (j<10000) {
try {
Thread.sleep(800l);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("2=========>"+j);
int jk = j;
new Thread(() -> {
String key = String.valueOf(" "+2+"-"+100000+jk);
lockUtils2.lock(key);
try {
System.out.println(new Date() + key+" 1 s ");
try {
Thread.sleep(1000);
} catch (Exception ex) {
}
System.out.println(new Date() + key+" 1 e ");
} finally {
lockUtils2.unLock(key);
}
}).start();
new Thread(() -> {
String key = String.valueOf(" "+2+"-"+100000+jk);
lockUtils2.lock(key);
try {
System.out.println(new Date() + key+" 2 s ");
try {
Thread.sleep(1000);
} catch (Exception ex) {
}
System.out.println(new Date() + key+" 2 e ");
} finally {
lockUtils2.unLock(key);
}
}).start();
j++;
}
}).start();
}
}
单个锁组处理
package com.coolsn.modules.tb.lockTools;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class LockUtils {
/**
* 用于存放读写锁对象与key
*/
private Map<String, EntityLockInfo> lConcurrentHashMap = new HashMap<String, EntityLockInfo>();
/**
* 用于存放所有锁信息,对弱需求锁进行清理
*/
private List<EntityLockInfo> keyInfos = new ArrayList<EntityLockInfo>();
/**
* 缓存锁的最大数量
*/
private Long lockMax = 3000l;
/**
* 当距离当前时间超过nowToDis时被认定为弱需求锁
*/
private Long nowToDis = 5000L;
/**
*
* @param lockMax
* @param nowToDis
*/
private LockUtils(long lockMax,Long nowToDis) {
this.lockMax = lockMax;
this.nowToDis = nowToDis;
}
protected static LockUtils init(long lockMax,Long nowToDis) {
return new LockUtils(lockMax, nowToDis);
}
/**
* 根据key进入锁
* @param key
*/
public synchronized void lock(String key) {
EntityLockInfo lockInfo = null;
//对缓存的锁进行弱需求锁维护,超过了缓存锁的最大数量则进行一次清理
if (keyInfos.size() >= lockMax) {
//清理一半
Integer indexHaf = Math.round(keyInfos.size()/2);
EntityLockInfo hafEntityLockInfo = keyInfos.get(indexHaf);
Long hafTime = hafEntityLockInfo.getTimestamp();
//判断这半节点是否超过nowToDis
if (new Date().getTime() - hafTime >= nowToDis) {
System.out.println("进行锁记录清理开始,锁长度:"+keyInfos.size());
//记录的锁已经超过最大锁数量进行清理,清理nowToDisPoint前面的
List<EntityLockInfo> dropKeyInfos = keyInfos.subList(0, indexHaf);
if (dropKeyInfos != null && dropKeyInfos.size() > 0) {
//新的锁记录
List<EntityLockInfo> newKeyInfos = keyInfos.subList(indexHaf, keyInfos.size());
//清理缓存锁
dropKeyInfos.forEach(item->{
Boolean itemLocked = item.isLocked();
if (!itemLocked) {
//表示未锁定,可清理
String itemKey = item.getKey();
lConcurrentHashMap.remove(itemKey);
}else {
//处于锁定的锁进行解锁
unLock(item.getKey());
}
});
//重置锁记录
if (newKeyInfos == null) {
newKeyInfos = new ArrayList<EntityLockInfo>();
}
keyInfos = newKeyInfos;
}
System.out.println("进行锁记录清理结束,锁长度:"+keyInfos.size());
}
}
//判断是否存在key对应的锁
if (lConcurrentHashMap.containsKey(key)) {
//存在取对应key的锁
lockInfo = lConcurrentHashMap.get(key);
}else {
//不存在创建新的锁
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
Lock writeLock = readWriteLock.writeLock();
lockInfo = new EntityLockInfo();
lockInfo.setKey(key);
lockInfo.setLock(writeLock);
lockInfo.setTimestamp(new Date().getTime());
//放入锁信息
keyInfos.add(lockInfo);
}
//使锁生效
lockInfo.lock();
//将锁放入存放
lConcurrentHashMap.put(key, lockInfo);
}
/**
* 根据key解开锁
* @param key
*/
public void unLock(String key) {
EntityLockInfo lockInfo = null;
//判断是否存在该key对应的锁
if (lConcurrentHashMap.containsKey(key)) {
//找到对应的锁对象
lockInfo = lConcurrentHashMap.get(key);
}else {
return;
}
//进行解锁
lockInfo.unLock();
lConcurrentHashMap.remove(key);
}
/**
* 判断是否被锁
* @param key
*/
public synchronized boolean beLocked(String key) {
EntityLockInfo lockInfo = null;
//判断是否存在该key对应的锁
if (lConcurrentHashMap.containsKey(key)) {
//找到对应的锁对象
lockInfo = lConcurrentHashMap.get(key);
return lockInfo.isLocked();
}else {
return false;
}
}
}
package com.coolsn.modules.tb.lockTools;
import java.util.concurrent.locks.Lock;
/**
* 键信息
* @author Think
*
*/
class EntityLockInfo {
/**
* 锁对象
*/
private Lock lock;
/**
*
* 键
*
*/
private String key;
/**
* 加入锁的时间节点
*/
private long timestamp;
/**
* 锁状态-是否是锁住
*/
private boolean locked;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public boolean isLocked() {
return locked;
}
public Lock getLock() {
return lock;
}
public void setLock(Lock lock) {
this.lock = lock;
}
public void unLock() {
this.lock.unlock();
this.locked = false;
}
public void lock() {
this.lock.lock();
this.locked = true;
}
}