1

ArrayList<short[]>インスタンス変数にアクセスする必要がある 2 つのスレッドがあります。

1 つのスレッドはshort[]、新しいデータが到着したときに、コールバックを介してアイテムを非同期的にリストに追加します。void dataChanged(short[] theData)

もう一方のスレッドは、リストに項目があるかどうかを定期的にチェックし、項目がある場合はすべての項目を反復処理して処理し、配列から削除します。

2 つのスレッド間の衝突を防ぐためにこれを設定するにはどうすればよいですか?

この不自然なコード例は現在、java.util.ConcurrentModificationException をスローします。

//instance vairbales
private ArrayList<short[]> list = new ArrayList<short[]>();

//asynchronous callback happening on the thread that adds the data to the list
void dataChanged(short[] theData) {
    list.add(theData);
}

//thread that iterates over the list and processes the current data it contains
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {

        while (true) {

            for(short[] item : list) {
                //process the data 
            }

            //clear the list to discared of data which has been processed. 
            list.clear(); 

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
});
4

6 に答える 6

7

代わりに、または同様の並行コレクションのようなプロデューサー コンシューマーキューを使用することをお勧めします。ArrayBlockingQueue

生産者と消費者の問題 (境界バッファー問題とも呼ばれます) は、マルチプロセス同期の問題の典型的な例です。この問題は、プロデューサーとコンシューマーの 2 つのプロセスが、キューとして使用される共通の固定サイズのバッファーを共有していることを示しています。プロデューサの仕事は、データの断片を生成し、それをバッファに入れて、最初からやり直すことです。同時に、コンシューマーは一度に 1 つずつデータを消費します (つまり、バッファーからデータを削除します)。問題は、バッファーがいっぱいの場合にプロデューサーがバッファーにデータを追加しようとしないこと、およびコンシューマーが空のバッファーからデータを削除しようとしないことを確認することです。

1 つのスレッドはoffersshort[]で、もう1 つのスレッドはtake()それらです。

于 2013-05-20T15:17:26.703 に答える
5

最も簡単な方法は、リストのタイプをスレッド セーフ リストの実装に変更することです。

private List<short[]> list = new CopyOnWriteArrayList<short[]>();

このタイプのリストは、頻繁に変更 (追加/削除) するとあまり効率的ではないことに注意してください。

さらに効率が必要な場合は、代わりに同期リストを使用できます。

private List<short[]> list = Collections.synchronizedList(new ArrayList<short[]>());

ただし、反復のために同期する必要があります。

synchronized(list) {
    for(short[] item : list) {
        //process the data 
    }
}

編集: a を使用する提案BlockingQueueはおそらく優れていますが、コードをさらに変更する必要があります。

于 2013-05-20T15:15:50.320 に答える
2

これについては、配列リストの代わりにブロッキングキューを調べることができます。

于 2013-05-20T15:18:19.740 に答える
0

Java の同期サポートを見てみましょう。

このページでは、指定されたオブジェクトでステートメントのグループを同期させる方法について説明します。つまり、そのオブジェクトで同期されたセクションを一度に実行できるのは 1 つのスレッドだけであり、他のスレッドはすべて待機する必要があります。

于 2013-05-20T15:18:20.160 に答える
0

ブロックを使用することもできますsynchronizedが、最善の解決策はスレッド間で変更可能なデータをまったく共有しないことだと思います。

各スレッドが独自のスペースに書き込むようにし、ワーカーが終了したときに結果を収集して集計します。

于 2013-05-20T15:18:21.443 に答える
0

http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#synchronizedList%28java.util.List%29

Collections クラスに、現在の ArrayList を同期リストにラップするように依頼できます。

于 2013-05-20T15:18:30.113 に答える