JCache EntryListener のコールバック メカニズムに問題があるようです。複数の jcache メンバー (hazelcast 実装) をセットアップしようとしていますが、それぞれがローカル マシン上の単一の Java アプリケーションとして実行されています (今のところ、ノードごとにメインを手動で開始する Ecipse で)。
ノードは最初に空のキャッシュを 1 つだけ保持し<Long, SpecificDataType>
ます。デフォルトの hazelcast-default.xml を使用して、主に CacheEntryListener を登録して、作成/更新/削除/期限切れのエントリの単純な sysout を生成する最小限の構成を独自にプログラムで準備しました。いくつか (3 つ以上) のメンバーを開始するとき、各メンバーが変更されたキーと値のペアを 1 回だけ印刷することを期待します。ここには、エントリが含まれています (操作エントリまたはバックアップ エントリとして)。問題は、場合によっては sysout が複数回表示されることです。これは、リスナーが頻繁に (複数回) トリガーされるように思われます。
たとえば、単純なクライアント (キャッシュを取得し、キー 123689 のエントリをキャッシュに入れるだけ) を使用してエントリを作成すると、sysout "CREATE EVENT RECEIVED" が 3 番目のメンバに 4 回表示され、より頻繁に4番目など...
CREATE EVENT RECEIVED:
Key: 123689, Value:SpecificDataType[...]
CREATE EVENT RECEIVED:
Key: 123689, Value:SpecificDataType[...]
CREATE EVENT RECEIVED:
Key: 123689, Value:SpecificDataType[...]
聞き手がどうにか累乗しているように見えます...何が間違っていますか? 構成に関して何か見逃していますか?
コード:
public static void main(String[] args) {
Member member = Member.getInstance();
try {
Cache<Long, SpecificDataType> cache = member.getCache("SpecificDataTypeCache", SpecificDataType.class);
System.out.println(cache);
} catch (Exception e) {
e.printStackTrace();
}
// shutdown loop
boolean shutdown = false;
while (!shutdown) {
if (new Scanner(System.in).nextLine().equals("shutdown")) {
shutdown = true;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// cache.clear();
member.shutdown();
}
public <T> Cache<Long, T> getCache(String name, Class<T> clazz) {
// configure the cache
MutableConfiguration<Long, T> config = new MutableConfiguration<Long, T>();
config.setStoreByValue(true).setTypes(Long.class, clazz)
.setExpiryPolicyFactory(AccessedExpiryPolicy.factoryOf(TEN_SEC))
.setStatisticsEnabled(false);
// create / get cache
Cache<Long, T> cache = cacheManager.getCache(name, Long.class, clazz);
if (cache == null) {
System.out.println("create cache");
cache = cacheManager.createCache(name, config);
// create the EntryListener
MyCacheEntryListener<Long, T> clientListener = new MyCacheEntryListener<Long, T>();
// using out listener, lets create a configuration
CacheEntryListenerConfiguration<Long, T> conf = new MutableCacheEntryListenerConfiguration<Long, T>(
FactoryBuilder.factoryOf(clientListener), null, false, true);
// register to cache
cache.registerCacheEntryListener(conf);
} else {
System.out.println("get cache");
}
return cache;
}
リスナーは可能な限り単純です。
public class MyCacheEntryListener<K, V> implements CacheEntryCreatedListener<K, V>,
CacheEntryUpdatedListener<K, V>, CacheEntryExpiredListener<K, V>,
CacheEntryRemovedListener<K, V>, Serializable {
@Override
public void onCreated(Iterable<CacheEntryEvent<? extends K, ? extends V>> cacheEntryEvents)
throws CacheEntryListenerException {
System.out.println("CREATE EVENT RECEIVED: ");
System.out.println(printEvent(cacheEntryEvents));
}
@Override
public void onExpired(Iterable<CacheEntryEvent<? extends K, ? extends V>> cacheEntryEvents)
throws CacheEntryListenerException {
System.out.println("EXPIRE EVENT RECEIVED: ");
System.out.println(printEvent(cacheEntryEvents));
}
@Override
public void onRemoved(Iterable<CacheEntryEvent<? extends K, ? extends V>> cacheEntryEvents)
throws CacheEntryListenerException {
System.out.println("REMOVE EVENT RECEIVED: ");
System.out.println(printEvent(cacheEntryEvents));
}
@Override
public void onUpdated(Iterable<CacheEntryEvent<? extends K, ? extends V>> cacheEntryEvents)
throws CacheEntryListenerException {
System.out.println("UPDATE EVENT RECEIVED: ");
System.out.println(printEvent(cacheEntryEvents));
}
private String printEvent(Iterable<CacheEntryEvent<? extends K, ? extends V>> cacheEntryEvents) {
StringBuilder sb = new StringBuilder();
final Iterator<CacheEntryEvent<? extends K, ? extends V>> iterator = cacheEntryEvents
.iterator();
while (iterator.hasNext()) {
final CacheEntryEvent<? extends K, ? extends V> next = iterator.next();
sb.append("Key: ");
sb.append(next.getKey());
sb.append(", Value:");
sb.append(next.getValue());
sb.append("\n");
}
return sb.toString();
}
}
どんな助けでも大歓迎です!