0

Java 7 ConcurrentLinkedQueue に関して次の質問があります。次のクラスがあるとします。

public class Blah {
    private ConcurrentLinkedQueue<String> queue;

    public Blah() {
        queue = new ConcurrentLinkedQueue<String>();
    }

    public void produce(String action, String task) throws InterruptedException {
        synchronized(queue) {
            while(queue.size() >= 8) 
                queue.wait();
            queue.add(action + "#" + task);
            queue.notifyAll();
        }
    }

    public void consume() throws InterruptedException {
        synchronized(queue) {
            while(queue.size() <= 0)
                queue.wait();
            String element = queue.poll();
            StringTokenizer strTok = new StringTokenizer(element, "#");
            String action = strTok.nextToken();
            String task = strTok.nextToken();
            /**
             * Operate on request
             */
            queue.notifyAll();
        }
    }
}

生成および消費関数は、リストのスレッドを生成/リストから削除するために、並行スレッドによって呼び出されます。キュー内の要素の追加/削除をシリアル化するために、以前の関数 consumer() および Produce() を実装します。上記は必須ですか、それとも ConcurrentLinkedQueue が処理しますか? コードのパフォーマンスを低下させたくないので、質問しています。

ありがとう、ニック

4

3 に答える 3

1

同期メカニズムから「最も遅い」組み込みの同期を使用しているため、コードのパフォーマンスが低下しました。

の完璧な使用例がありBlockingQueueます。これにより、スペース/要素が利用可能になるまでブロックする操作が提供さputれます。take

ConcurrentLinkedQueue同期ではなくスレッドセーフのみを提供します。これは、マルチスレッド アプリケーションでキューから要素を安全に追加/削除できることを意味しますが、スペース/要素を待機するメカニズムが提供されないため、その目的のために wait()、notify() メソッドを正しく使用しました (ただし、他の共有オブジェクトでも同期されるため、そのキューである必要はありませんでした)。Java では、同期の代わりに Lock を使用する方がはるかに高速です。

于 2015-04-12T22:10:24.977 に答える
1

TL;DR:Queue非ブロッキングになるように特別に設計された を として使用していBlockingQueueます。

コードは次のように書き換えることができます。

public class Blah {
    private BlockingQueue<String> queue;

    public Blah() {
        queue = new LinkedBlockingQueue<>(8);
    }

    public void produce(String action, String task) throws InterruptedException {
        while (true) {
            queue.put(action + "#" + task);
        }
    }

    public void consume() throws InterruptedException {
        while (true) {
            final String[] data = queue.take().split("#");
            final String action = data[0];
            final String task = data[1];
        }
    }
}

は要素BlockingQueueで囲まれています。キューがいっぱいになるとブロックされます。キューが空の場合はブロックされます。8puttake

同期は必要ありません。

また、StringTokenizer非推奨です。class次のようなものを使用することをお勧めします。

public class Data {
    private final String action;
    private final String task;

    public Data(final String action, final String task) {
        this.action = action;
        this.task = task;
    }

    public String getAction() {
        return action;
    }

    public String getTask() {
        return task;
    }
}

データを交換するため。sを作成して解析する理由はありませんString

于 2015-04-12T22:38:13.517 に答える
-2

と が独立して呼び出されると仮定するとproduceconsumeどちらもキュー オブジェクトをロックしようとするconsumeため、要素が見つからないため、ロックを解放することは決してないため、おそらく無限ループに陥るでしょう。同期ロジックは、おそらく と を呼び出すメソッドに実装する必要がconsumeありproduceます。

于 2015-04-12T22:17:00.397 に答える