オブザーバーパターンとBlockingQueueを使用してインスタンスを追加しています。別のメソッドでキューを使用していますが、次のように実行しているにもかかわらず、take()が永久に待機しているようです。
/** {@inheritDoc} */
@Override
public void diffListener(final EDiff paramDiff, final IStructuralItem paramNewNode,
final IStructuralItem paramOldNode, final DiffDepth paramDepth) {
final Diff diff =
new Diff(paramDiff, paramNewNode.getNodeKey(), paramOldNode.getNodeKey(), paramDepth);
mDiffs.add(diff);
try {
mDiffQueue.put(diff);
} catch (final InterruptedException e) {
LOGWRAPPER.error(e.getMessage(), e);
}
mEntries++;
if (mEntries == AFTER_COUNT_DIFFS) {
try {
mRunner.run(new PopulateDatabase(mDiffDatabase, mDiffs));
} catch (final Exception e) {
LOGWRAPPER.error(e.getMessage(), e);
}
mEntries = 0;
mDiffs = new LinkedList<>();
}
}
/** {@inheritDoc} */
@Override
public void diffDone() {
try {
mRunner.run(new PopulateDatabase(mDiffDatabase, mDiffs));
} catch (final Exception e) {
LOGWRAPPER.error(e.getMessage(), e);
}
mDone = true;
}
一方、mDiffQueueはLinkedBlockingQueueであり、次のように使用しています。
while (!(mDiffQueue.isEmpty() && mDone) || mDiffQueue.take().getDiff() == EDiff.INSERTED) {}
しかし、mDoneがtrueではないのに最初の式がチェックされていると思います。その後、mDoneがtrueに設定されている可能性があります(オブザーバーは常にマルチスレッドですか?)が、すでにmDiffQueue.take()を呼び出していますか?:-/
編集:私は本当に今それを取得していません。最近、次のように変更しました。
synchronized (mDiffQueue) {
while (!(mDiffQueue.isEmpty() && mDone)) {
if (mDiffQueue.take().getDiff() != EDiff.INSERTED) {
break;
}
}
}
デバッガーで少し待つと動作しますが、mDoneがfalseに初期化され、while条件がtrueになり、本体が実行されるため、「リアルタイム」でも動作するはずです。
mDiffQueueが空で、mDoneがtrueの場合、whileループの本体をスキップする必要があります(つまり、キューはもういっぱいになりません)。
編集:それはそうです:
synchronized (mDiffQueue) {
while (!(mDiffQueue.isEmpty() && mDone)) {
if (mDiffQueue.peek() != null) {
if (mDiffQueue.take().getDiff() != EDiff.INSERTED) {
break;
}
}
}
}
なぜpeek()が必須なのかわかりませんが。
編集:
私がしているのはツリーを反復処理することであり、すべてのINSERTEDノードをスキップしたいと思います。
for (final AbsAxis axis = new DescendantAxis(paramRtx, true); axis.hasNext(); axis.next()) {
skipInserts();
final IStructuralItem node = paramRtx.getStructuralNode();
if (node.hasFirstChild()) {
depth++;
skipInserts();
...
基本的に、ツリーの別のリビジョンで削除されたノードを考慮せずに、ツリーの最大深度またはレベルを計算します(サンバーストの視覚化の比較のため)が、それは範囲外である可能性があります。最大深度を調整しているだけでも、挿入されていないノードで何かをしていることを説明するためだけに。
よろしく、
ヨハネス