Удалить неиспользуемый 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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

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