有没有更简单的方法来使用锁并发映射?

Is trere a simplier way to have concurrentmap with locks?

我需要锁定每个实体 ID 的某些功能。

private final ConcurrentMap<Long, Lock> idLocks = Maps.newConcurrentMap();

public void doSmth(Long id){
    ReentrantLock newLock = new ReentrantLock();
    Lock lock = prLocks.putIfAbsent( id, newLock ); //returns null for first run for this id
    if (null == lock) { //have to do null checking 
        lock = newLock;
    }
    if (lock.tryLock()){
        try {
        //some code here
        } finally {
            lock.unlock();
        }
    }
}

有没有办法 运行 Lock lock = returnExistingOrPutAndReturnNew( id, newLock ); 摆脱空检查?

没有,ConcurrentMap中没有这个方法,但是可以使用guava LoadingCache:

private final LoadingCache<Long, Lock> idLocks = CacheBuilder.newBuilder()
       .build(
             new CacheLoader<Long, Lock>() {
                   public Lock load(Long id) throws AnyException {
                       return new ReentrantLock();
                   }
             });

public void doSmth(Long id){
     Lock lock = prLocks.get(id); //always return not-null Lock
     if (lock.tryLock()){
          try {
             //some code here
          } finally {
             lock.unlock();
          }
     }
 }

更新:

在java8中可以使用Map#computeIfAbsent方法:

public void doSmth(Long id){
    Lock lock = prLocks.computeIfAbsent(id, key -> new ReentrantLock());
    if (lock.tryLock()){
        try {
            //some code here
        } finally {
            lock.unlock();
        }
    }
}