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; 

    }

我想从 put() 通知在 Take() 中等待的线程,反之亦然。有人可以帮助我以正确的方式做到这一点。

我检查了 java.utils 的实现,它使用了 Condition 和 ReentrantLocks,这对我来说在这个阶段有点复杂。为了简单起见,我现在可以不完全健壮[但正确]。

谢谢 !

4

1 回答 1

2

简短的回答是,请致电notifyAll()您有评论的地方 //How to notify threads waiting during take()

现在为了更完整的答案......

阅读的参考是:Java Concurrency in Practice。你的问题的答案就在里面。

但是,为了简要回答您的问题:在 Java 中,线程通过锁定同一个对象并使用wait()notify()安全地更改状态来同步。典型的简化流程是:

  1. 线程 A 通过在锁对象上输入一个synchronized块来获得锁
  2. 线程 A 在循环中检查某些条件,如果不是“OK to go”调用thread.wait(),这是一个“释放”锁的阻塞调用,因此在同一锁对象上同步的其他代码可以继续
  3. 线程 B 获得相同的锁,并可能做一些改变线程 A 等待的条件的事情。当它调用时notifyAll(),线程 A 将唤醒并重新检查条件并(可能)继续

关于同步需要记住的一些事情是:

  • 它是关于通过更改状态atomic来保持对象状态的一致性。“原子”意味着保证完成整个更改(例如多个字段)(没有部分更改,因此不一致)
  • 它是合作的——在给定的锁对象上同步的代码具有共同的状态,即正在改变的状态和允许状态改变的条件——你waitnotify大约相同的“主体”。状态的每个部分都应该由它自己的锁对象来保护——通常是一个私有字段,例如private Object lock = new Object();就可以了
  • 同步this的方法用作锁定对象 - 这样做很容易但可能很昂贵,因为您为每次调用锁定,而不是仅在需要时锁定
  • 同步的静态方法使用 Class 对象作为锁对象
于 2011-06-27T01:39:57.510 回答