1

Java マルチスレッド構造を理解しようとしています。また、ブロッキング キューの簡単な実装を書こうとしています。ここに私が書いたコードがあります:

  class BlockingBoundedQueue<E>
    {
        @SuppressWarnings("unchecked")
        BlockingBoundedQueue(int size)
        {
            fSize = size;
            fArray = (E[]) new Object[size];
//            fBlockingQueue = new ArrayBlockingQueue<E>(size);
        }

        BlockingQueue<E> fBlockingQueue;

        public synchronized void put(E elem)
        {
            if(fCnt==fSize-1)
            {
                try
                {
                    // Should I be waiting/locking on the shared array instead ? how ?
                    wait();
                }
                catch (InterruptedException e)
                {
                    throw new RuntimeException("Waiting thread was interrupted during put with msg:",e);
                }
            }
            else
            {
                fArray[fCnt++]=elem;
                //How to notify threads waiting during take()
            }
        }


        public synchronized E take()
        {
            if(fCnt==0)
            {
                try
                {
                    // Should I be waiting/locking on the shared array instead ? how ?
                    wait();
                }
                catch (InterruptedException e)
                {
                    throw new RuntimeException("Waiting thread was interrupted during take with msg:",e);
                }
            }

            return fArray[fCnt--];
            //How to notify threads waiting during put()
        }
        private int fCnt;
        private int fSize;
        private E[] fArray; 

    }

Take() で待機しているスレッドに put() から、またはその逆に通知したい。誰かがこれを行う正しい方法を教えてください。

java.utils の実装を確認したところ、この段階では少し複雑な Condition と ReentrantLocks が使用されています。今のところ、簡単にするために、完全に堅牢でなくても大丈夫です[しかし正しい].

ありがとう !

4

1 に答える 1

2

簡単な答えは、notifyAll()コメントがある場所 に電話することです//How to notify threads waiting during take()

今、より完全な答えのために...

参照先は次のとおりです。 Java Concurrency in Practice。あなたの質問に対する答えはそこにあります。

ただし、質問に簡単に答えると、Java では、スレッドは同じオブジェクトをロックし、 and を使用wait()notify()て状態を安全に変更することで同期します。一般的な単純化されたフローは次のとおりです。

  1. synchronizedスレッド Aは、ロック オブジェクトのブロックに入ることによってロックを取得します。
  2. スレッド A は、「OK to go」呼び出しthread.wait()ではない場合、ループ内のいくつかの条件をチェックします。これは、ロックを「解放」するブロッキング呼び出しであり、同じロック オブジェクトで同期された他のコードを続行できます。
  3. スレッド B は同じロックを取得し、スレッド A が待機している状態を変更する何かを行う可能性があります。が呼び出されるとnotifyAll()、スレッド A が起動して状態を再チェックし、(可能性があります) 続行します

同期については、次の点に注意してください。

  • これは、状態をアトミックに変更することによって、オブジェクトの状態の一貫性を維持することです。「アトミック」とは、変更全体 (複数のフィールドなど) が完了することが保証されていることを意味します (部分的で一貫性のない変更はありません)。
  • それは協調的です-特定のロックオブジェクトで同期されたコードは、変更されている状態とその状態の変更を許可する条件に共通しています-あなたwaitnotifyほぼ同じ「サブジェクト」。状態の各部分は、独自のロック オブジェクトで保護する必要があります。通常はプライベート フィールドです。たとえば、private Object lock = new Object();これで問題ありません。
  • 同期されたメソッドはロック オブジェクトとして使用します。これを行うのは簡単ですが、必要なときだけでなく呼び出しごとthisにロックするため、コストがかかる可能性があります。
  • 同期される静的メソッドは、Class オブジェクトをロック オブジェクトとして使用します。
于 2011-06-27T01:39:57.510 に答える