I have a requireement to have locks in some function per entity 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();
}
}
}
Is there a way to run Lock lock = returnExistingOrPutAndReturnNew( id, newLock );
to get rid of null checking?
No, there is no such method in ConcurrentMap, but you can use 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();
}
}
}
UPDATE:
In java 8 you can use Map#computeIfAbsent method:
public void doSmth(Long id){
Lock lock = prLocks.computeIfAbsent(id, key -> new ReentrantLock());
if (lock.tryLock()){
try {
//some code here
} finally {
lock.unlock();
}
}
}