Удалить неиспользуемый ReentrantLock из ConcurrentHashMap.JAVA

Программисты JAVA общаются здесь
Anonymous
Удалить неиспользуемый ReentrantLock из ConcurrentHashMap.

Сообщение Anonymous »

У меня есть метод в службе, который извлекает объект, если он существует, в противном случае он создает новый и возвращает (для целей вопросов предположим, что объект представляет собой просто строку).
Метод выполняется несколькими потоками, поэтому, если два из них вызовут метод getOrCreateEntity с одинаковым значением и в то же время, они могут закончить созданием двух идентичных объектов, поэтому следующий вызов getEntity вернет два одинаковых объекты, где разрешено только одно.
Я пытался заблокировать каждое уникальное имя объекта, объединив ConcurrentHashMap с ReentrantLock, в целом это работает довольно хорошо, проблемы возникают, когда я пытаюсь удалить запись карты с блокировкой, которая больше не нужна, а затем в какой-то момент я получаю NullPointerException, когда я вызываю метод unlock().
Мне нужна правильная синхронизация для каждого уникального значения.
Мой фиктивный класс для проверки концепции работы

Код: Выделить всё

public class EntityService {

private static final ConcurrentHashMap lockMap = new ConcurrentHashMap();

private static final List entityList = new ArrayList();

public String getOrCreateEntity(String entityName){
lockMap.putIfAbsent(entityName, new ReentrantLock());
lockMap.get(entityName).lock();
try {
return getEntity(entityName).orElseGet(() -> createEntity(entityName));
} finally {
lockMap.get(entityName).unlock(); //  tabName.equals(entityName))
.collect(Collectors.toList());

if(result.size() > 1){
throw new RuntimeException();
} else if (result.size() == 1) {
return Optional.of(result.get(0));
} else {
return Optional.empty();
}
}
}
Мой тестовый пример довольно прост

Код: Выделить всё

class ReentrantLockServiceTest extends Specification {

def service = new EntityService()

def executor = Executors.newFixedThreadPool(200)

def "test lock"(){
expect:
for (i in 0..20000) {
executor.execute{ -> service.getOrCreateEntity(RandomUtils.nextInt(1,4) as String) }
}
Thread.sleep(5000)
}

}
Чего мне не хватает? Может быть, есть лучшие классы параллелизма для выполнения желаемого поведения?

Подробнее здесь: https://stackoverflow.com/questions/673 ... enthashmap

Вернуться в «JAVA»