1

タイトルにあるように、スレッドベースの構造に問題があります。私がする必要があるのは:

  • 1つのスレッドがループで実行され、リストに何かが存在するかどうかを確認し、存在する場合は、オブジェクトに対して何らかの操作を実行してから、リストから削除します

  • 'outside'から呼び出され、このリストに新しいオブジェクトを追加する関数。

これが私のアプローチです:

public class Queue implements Runnable {
    private List<X> listOfObjects = new ArrayList<X>;

    public void addToList(X toAdd){
        listOfObject.add(toAdd);
    }

    public void run() {
        while(true){
            synchronized(listOfObjects){
            if(!listOfObjects.isEmpty()){
                listOfObjects.get(0).doSth();
                listOfObjects.remove(0);
            }
            }
        }
    }
}

それは適切なアプローチですか?このリストへの追加も同期する必要がありますか?

4

4 に答える 4

9

独自に作成するのではなく、java.util.concurrent.BlockingQueueの実装を試す必要があるようです。LinkedBlockingQueueがうまく機能すると思います複数のソースからキューにエントリを書き込むことができ、コンシューマスレッドは各エントリを削除して、スレッドセーフな方法で順番に処理します。

のコンシューマースレッドは(メソッドを呼び出すことによって)待機することに注意BlockingQueueしてくださいtake()。ただし、上記の実装では、キューでエントリが処理されるのを待っている間、CPUが回転して消費されます(これを実行してCPU使用率を監視すると、これは明らかです)。

これが説明記事です。

于 2012-10-02T13:20:25.630 に答える
1

リストへのすべてのアクセスを同期する必要があります。

public void addToList(X toAdd){
    synchronized(listOfObject) {
        listOfObject.add(toAdd);
    }
}

または、 CopyOnWriteArrayListなどのListのスレッドセーフな実装を使用することもできます。その場合、すべてのsynchronizedブロックを削除できます。

ps:別の回答で述べたように、ArrayBlockingQueueを再実装しているように見えます。

于 2012-10-02T13:21:03.513 に答える
1

Collections.synchronizedList()手動で同期されたブロックの代わりにラッパーを使用することをお勧めします。

于 2012-10-02T13:22:22.600 に答える
1

追加された要素を処理するスレッドのキューを作成しようとしているようです。

より簡単なアプローチは、ExecutorServiceを使用することです。

ExecutorService service = Executors.newSingleThreadedPool();

// to add a task.
service.submit(new Runnable() {
    public void run() {
       // process X here
    }
});
于 2012-10-02T13:22:26.423 に答える