如何在阻塞队列实现中正确使用java notify

时间:2011-06-27 00:52:24

标签: java multithreading thread-safety blockingqueue

我正在尝试理解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,这对我来说有点复杂。为了简单起见,我现在没有完全健壮[但是正确]。

谢谢!

1 个答案:

答案 0 :(得分: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将被唤醒并重新检查条件并且(可能)继续
  4. 有关同步的一些注意事项是:

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