記錄Apache Curator NodeCache的一個(gè)坑
NodeCache nodeCache = new NodeCache(client, path.fullPath());
nodeCache.start(true);
System.out.println(nodeCache.getCurrentData()); // data是1
client.setData()
.forPath(path.fullPath(), new byte[]{2}); // data是2
System.out.println(nodeCache.getCurrentData());
nodeCache.close();
預(yù)期結(jié)果是第一次print看到data是1,改變了節(jié)點(diǎn)的數(shù)據(jù)之后芽狗,第二次print出來(lái)應(yīng)該是新數(shù)據(jù)。
NodeCache應(yīng)該在節(jié)點(diǎn)的數(shù)據(jù)變化的時(shí)候,自動(dòng)更新內(nèi)部的data焰枢。
然而實(shí)際運(yùn)行結(jié)果,第一次和第二次都是1
原因是NodeCache更新內(nèi)部data是在另一個(gè)線程做的(后面稱作更新線程)舌剂,主線程比更新線程要快济锄,主線程走到第二個(gè)print的時(shí)候,更新線程還沒(méi)更新好霍转,所以主線程看到的還是更新前的數(shù)據(jù)荐绝。
解決方法
nodeCache.getCurrentData這一個(gè)操作不在主線程做,用listener處理node數(shù)據(jù)變化之后的業(yè)務(wù)邏輯避消。
nodeCache.getListenable().addListener(() -> {
System.out.println(nodeCache.getCurrentData());
// 業(yè)務(wù)邏輯
});
如果需要等listener線程處理完之后低滩,主線程才可以退出,可以用countdownlatch之類的線程同步方式岩喷。
CountDownLatch latch = new CountDownLatch(1);
NodeCache nodeCache = new NodeCache(client, path.fullPath());
nodeCache.getListenable().addListener(() -> {
System.out.println(nodeCache.getCurrentData()); // 更新后的數(shù)據(jù)
latch.countDown();
// 業(yè)務(wù)邏輯
});
nodeCache.start(true);
System.out.println(nodeCache.getCurrentData()); // 初始數(shù)據(jù)
client.setData()
.forPath(path.fullPath(), new byte[]{2});
latch.await();
nodeCache.close();