问题描述
我有一个服务中的方法,如果存在则获取实体,否则它会创建新的实体并返回(出于问题的目的,假设实体只是一个字符串)。
方法由多个线程执行,因此如果其中两个将同时调用具有相同值的方法 getorCreateEntity
,那么他们可以完成创建两个相同的对象,因此下一个 getEntity
调用将返回两个相同的对象,只允许一个。
我尝试通过将 ConcurrentHashMap
与 reentrantlock
结合来为每个唯一的实体名称锁定,一般来说效果很好,当我尝试使用不再需要的锁定删除地图条目时会出现问题,然后我在调用 NullPointerException
方法时得到 unlock()
。
我希望每个唯一值都正确同步。
我的虚拟班级来测试工作概念
public class EntityService {
private static final ConcurrentHashMap<String,reentrantlock> lockMap = new ConcurrentHashMap<>();
private static final List<String> 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(); // <--- Nullpointer
if(lockMap.containsKey(entityName) && !lockMap.get(entityName).isLocked()){
lockMap.remove(entityName);
}
}
}
private String createEntity(String entityName){
entityList.add(entityName);
return entityName;
}
private Optional<String> getEntity(String entityName){
List<String> result = entityList.stream()
.filter(tabName -> 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)
}
}
我错过了什么?也许有更好的并发类来执行我想要的行为?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)