ReentrantReadWriteLock 锁转为关键字锁使用

当然分布式并不适用

使用示例

获取锁组

/**
*
* 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;
		
	}
	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值