首页 > 开发 > Java > 正文

java 使用ConcurrentHashMap和计数器实现锁

2024-07-13 10:08:15
字体:
来源:转载
供稿:网友

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教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表