我们正试图找出使用Hazelcast的IMap的最佳方法,而不使用悲观锁定。
EntryProcessor似乎是正确的选择,但是我们需要应用两种不同类型的操作:'创建'当containsKey为false时,&'39; update'当containsKey为真时。
如何利用EntryProcessor支持这些逻辑检查?
如果两个线程同时命中containsKey()并且它们都返回false,我不希望它们都创建密钥。我希望第二个帖子能够应用更新。
这是我们到目前为止所做的:
public void put(String key, Object value) {
IMap<String, Object> map = getMap();
if (!map.containsKey(key)) {
// create key here
} else {
// update existing value here
// ...
map.executeOnKey(key, new TransactionEntryProcessor({my_new_value}));
}
}
private static class MyEntryProcessor implements
EntryProcessor<String, Object>, EntryBackupProcessor<String, Object>, Serializable {
private static final long serialVersionUID = // blah blah
private static final ThreadLocal<Object> entryToSet = new ThreadLocal<>();
MyEntryProcessor(Object entryToSet) {
MyEntryProcessor.entryToSet.set(entryToSet);
}
@Override
public Object process(Map.Entry<String, Object> entry) {
entry.setValue(entryToSet.get());
return entry.getValue();
}
@Override
public EntryBackupProcessor<String, Object> getBackupProcessor() {
return MyEntryProcessor.this;
}
@Override
public void processBackup(Map.Entry<String, Object> entry) {
entry.setValue(entryToSet.get());
}
}
你可以看到两个线程可以进入put方法并同时调用containsKey。第二个将覆盖第一个结果。
答案 0 :(得分:3)
按定义,EntryProcessor是一个处理逻辑,它在条目本身上执行,无需序列化/反序列化该值。在内部,EP由分区线程执行,其中一个分区线程负责多个分区。当EP到达HC时,它由密钥所属的分区的所有者线程选择。一旦处理完成,分区线程就可以接受并执行其他任务(对于相同的密钥,可能是相同的EP,由另一个线程提交)。因此,看起来似乎如此,但不应将EP用作悲观锁定的替代方案。
如果您坚持并且非常热衷于使用EP,那么您可以尝试在进程方法中进行空检查。像这样:
public Object process(Map.Entry<String, Object> entry) {
if(null == entry.getValue()) {
entry.setValue("value123");
}
return entry.getValue();
}
这样会发生两件事: 1.另一个线程将等待分区线程再次可用 2.由于该值已存在,因此您不会覆盖任何内容