在我的 android 应用程序中,我有 LinkedBlockingQueue 的 HashMap:
private ConcurrentHashMap<Integer, LinkedBlockingQueue<short[]>> mBuffer = new ConcurrentHashMap<Integer, LinkedBlockingQueue<short[]>>(8,0.9f,1);
每个键都有单独的线程生成数据。数据以这种方式添加:
public void addFrameCopy(Integer sampleId, short[] frame) {
LinkedBlockingQueue<short[]> value;
if (!mBuffer.containsKey(id)) {
value= new LinkedBlockingQueue<short[]>();
mBuffer.put(id, value);
} else {
value = mBuffer.get(sampleId);
}
Log.d("IN "+id,inCounter+" "+getShortArraySum(frame)+"");
inCounter++;
value.add(Arrays.copyOf(frame,frame.length));
}
所有键都有一个消费者线程。消费是这样运作的:
public List<Pair<ControlFrame, short[]>> getCombinedFramesBatchSkipWhenNeeded
(List<Pair<Integer, ControlFrame>> controlFrames,
List<Pair<ControlFrame, short[]>> out) {
Set<Integer> nonUsedKeys = mBuffer.keySet();
LinkedBlockingQueue<short[]> list;
short[] takenDataFrame;
for (Pair<Integer, ControlFrame> controlPair : controlFrames) {
if (shouldSatisfyControlFrame(controlPair.second)) {
list=mBuffer.get(controlPair.first);
try {
takenDataFrame = list.take();
} catch (InterruptedException e) {
e.printStackTrace();
continue;
}
Pair<ControlFrame, short[]> combinedFrame = new Pair<ControlFrame, short[]>(controlPair.second, takenDataFrame);
Log.d("OUT "+controlPair.first,outCounter+" "+getShortArraySum(takenDataFrame)+"");
outCounter++;
out.add(combinedFrame);
nonUsedKeys.remove(controlPair.first);
} else {
attemptToSkipFrames(controlPair);
}
}
for (Integer key : nonUsedKeys) {
Log.d("OUT "+key,"Skip");
list=mBuffer.get(key);
if(!list.isEmpty())
list.remove(0);
}
return out;
}
从未调用方法 attemptToSkipFrames。 我正在为一个生产线程运行测试。这是我得到的日志:
IN 9﹕ 0 0
OUT 9﹕ 0 0
IN 9﹕ 1 26494
OUT 9﹕ 1 26494
IN 9﹕ 2 203342
IN 9﹕ 3 -427941
IN 9﹕ 4 31709
OUT 9﹕ 2 203342
IN 9﹕ 5 457126
OUT 9﹕ 3 457126
看起来没有。 2是清除列表,导致没有。 3 获取插入的值。 5. 如何防止丢失元素?
简化
用于在没有 hashmap 代码的情况下插入和获取数据的方法。
public void addFrameCopy(Integer sampleId, short[] frame) {
LinkedBlockingQueue<short[]> value=getQueue(sampleId);
Log.d("IN "+id,inCounter+" "+getShortArraySum(frame)+"");
inCounter++;
value.add(Arrays.copyOf(frame,frame.length));
}
public List<Pair<ControlFrame, short[]>> getCombinedFramesBatchSkipWhenNeeded
(List<Pair<Integer, ControlFrame>> controlFrames,
List<Pair<ControlFrame, short[]>> out) {
LinkedBlockingQueue<short[]> list;
short[] takenDataFrame;
for (Pair<Integer, ControlFrame> controlPair : controlFrames) {
list=getQueue(controlPair.first);
try {
takenDataFrame = list.take();
} catch (InterruptedException e) {
e.printStackTrace();
continue;
}
Pair<ControlFrame, short[]> combinedFrame = new Pair<ControlFrame, short[]>(controlPair.second, takenDataFrame);
Log.d("OUT "+controlPair.first,outCounter+" "+getShortArraySum(takenDataFrame)+"");
outCounter++;
out.add(combinedFrame);
}
return out;
}
最佳答案
在按照 Ralf 的建议/要求玩它的简化单类版本时,我设法找到了错误。事实证明问题是由手动删除 HashMap 键引起的,而不是队列中的某些并发问题。通过更改修复它
Set<Integer> nonUsedKeys = mBuffer.keySet();
到
Set<Integer> nonUsedKeys = new LinkedHashSet<Integer>(mBuffer.keySet());
关于java - Android LinkedBlockingQueue 取清空列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26799266/