Android LinkedBlockingQueue采取清算清单

时间:2014-11-07 10:35:31

标签: java android multithreading concurrency queue

在我的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;
}

方法尝试永远不会调用ToskipFrames。 我正在为一个生产线程运行测试。这是我得到的日志:

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将值插入为no。 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;
}

1 个答案:

答案 0 :(得分:1)

在按照Ralf的建议/要求玩简化的单一版本时,我设法找到了bug。事实证明问题是由删除hashmap键的manul,而不是队列中的一些concurency问题引起的。通过更改

修复了它
Set<Integer> nonUsedKeys = mBuffer.keySet();

Set<Integer> nonUsedKeys = new LinkedHashSet<Integer>(mBuffer.keySet());