• 技术文章 >Java >java教程

    java如何使用ConcurrentHashMap与计数器来实现锁的详解

    黄舟黄舟2017-05-28 09:12:34原创1254
    这篇文章主要介绍了java 使用ConcurrentHashMap和计数器实现锁的相关资料,需要的朋友可以参考下

    java 使用ConcurrentHashMap和计数器实现锁

    在某些场景下,我们想让线程根据某些业务数据进行排队,简单代码如下:

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class TestServiceImpl {
      private static ConcurrentHashMap<Long, LockObj> lockMap = new ConcurrentHashMap<Long, LockObj>(40);
    
      public void test(Long userId){
        LockObj lock = tryLock(userId);
        synchronized (lock) {
          try{
            //处理业务
          }
          finally{
            unLock(lock);
          }
        }
      }
    
      private LockObj tryLock(Long key) {
        LockObj curVal = new LockObj(key);
        LockObj preVal = lockMap.putIfAbsent(key, curVal);
        if (null == preVal) {
          curVal.inc();
          return curVal;
        }
        else{
          preVal.inc();
        }
        return preVal;
      }
    
      private void unLock(LockObj lock){
        if (lock.dec() <= 0){
          lockMap.remove(lock.getKey());
        }
      }
    
      public class LockObj {
        private long key = 0;
        private AtomicInteger count = new AtomicInteger(0);
    
        public LockObj(long key){
          this.key = key;
        }
    
        public int inc(){
          return count.incrementAndGet();
        }
        public int dec(){
          return count.decrementAndGet();
        }
    
        public long getKey(){
          return key;
        }
    
        @Override
        public String toString() {
          return "LockObj [key=" + key + ", count=" + count + "]";
        }
      }
    
    }

    按照userId来排队,如果每个线程处理数据后不释放锁的话,那么可以不利用计数器。但是加了释放锁的操作,则必须加上计算器。因为当线程把锁释放掉后,还没来得及退出synchronized 代码块时,另外一个线程调用了tryLock方法,那该线程将拿到另外一个对象的锁,导致利用synchronized 关键字进行userId排队失败。

    也可以利用guava的API来实现。

    import com.google.common.collect.Interner;
    import com.google.common.collect.Interners;
    
    
    public class TestServiceImpl {
    
      Interner<String> pool = Interners.newWeakInterner();
    
      public void test(Long userId) throws OspException {
    
        synchronized ( pool.intern(String.valueOf(userId))){
          //处理业务操作
        }
      }
    }

    以上就是java如何使用ConcurrentHashMap与计数器来实现锁的详解的详细内容,更多请关注php中文网其它相关文章!

    声明:本文原创发布php中文网,转载请注明出处,感谢您的尊重!如有疑问,请联系admin@php.cn处理
    上一篇:java中ThreadPoolExecutor并发调用的实例代码分析 下一篇:关于Java中异步编程的实践详解
    大前端线上培训班

    相关文章推荐

    • 理解java8中java.util.function.*pojo反射新方法(附代码)• 浅析安卓app和微信授权登录及分享完整对接(代码分享)• 一招教你使用java快速创建Map(代码分享)• 教你一招搞定时序数据库在Spring Boot中的使用• 一文讲解Java中初始化List集合的8种方式(附代码)

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网