java - 在 Java 中实现自己的阻塞队列

标签 java multithreading synchronization java.util.concurrent blockingqueue

我知道这个问题之前已经被问过和回答过很多次了,但我就是想不出在互联网上找到的例子中的技巧,比如 thisthat一个。

这两种解决方案都在 put() 方法中检查阻塞队列的数组/队列/链表是否为 notifyAll 等待线程,反之亦然 get () 方法。 comment在第二个链接中强调了这种情况并提到没有必要。

所以问题是;检查队列是否为空对我来说似乎也有点奇怪 | full 通知所有等待线程。有什么想法吗?

提前致谢。

最佳答案

我现在知道这是一个老问题了,但是在阅读了问题和答案之后我忍不住了,我希望你觉得这个有用。

关于在通知其他等待线程之前检查队列实际上是满的还是空的,你遗漏了一些方法 put (T t)T get() 都是synchronized 方法,意味着一次只有一个线程可以进入这些方法中的一个,但这并不妨碍它们一起工作,所以如果线程-a 进入了 put (T t) 方法另一个线程-b 仍然可以在线程-a 退出之前进入并开始执行 T get() 方法中的指令 put (T t),因此这种双重检查设计将使开发人员感到更安全一点,因为您无法知道 future 是否会或何时会发生 cpu 上下文切换。

更好和更推荐的方法是使用可重入锁条件:

//我已经编辑了这个 link 的源代码

Condition isFullCondition;
Condition isEmptyCondition;
Lock lock;

public BQueue() {
    this(Integer.MAX_VALUE);
}

public BQueue(int limit) {
    this.limit = limit;
    lock = new ReentrantLock();
    isFullCondition = lock.newCondition();
    isEmptyCondition = lock.newCondition();
}

public void put (T t) {
    lock.lock();
    try {
       while (isFull()) {
            try {
                isFullCondition.await();
            } catch (InterruptedException ex) {}
        }
        q.add(t);
        isEmptyCondition.signalAll();
    } finally {
        lock.unlock();
    }
 }

public T get() {
    T t = null;
    lock.lock();
    try {
        while (isEmpty()) {
            try {
                isEmptyCondition.await();
            } catch (InterruptedException ex) {}
        }
        t = q.poll();
        isFullCondition.signalAll();
    } finally { 
        lock.unlock();
    }
    return t;
}

使用这种方法不需要双重检查,因为lock对象在两种方法之间共享,这意味着只有一个线程a或b可以进入其中任何一个与创建不同监视器的同步方法不同,只有那些因为队列已满而等待的线程才会在有更多空间时得到通知,对于因为队列为空而等待的线程也是如此,这将导致更好的 cpu利用。 你可以在源代码中找到更详细的示例 here

关于java - 在 Java 中实现自己的阻塞队列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20110013/

相关文章:

c++ - std::thread() 和 std::ref() 在类内部使用时导致构建错误

Java 并发 : concurrently adding & purging List entries

java - 关闭 ANTLR4 CharStream(Java 运行时)- OutOfMemoryException

ruby-on-rails - Ruby on Rails 同时发出多个 HTTP 请求?

java - 流数据解决方案(Java、Python、socket.io、Node JS)

python线程安全对象缓存

java - 尽管保护写操作仍获取竞争条件 - Java

c++ - 为什么图书馆要在 Windows 上实现自己的基本锁?

java - 运行时执行 (JAR) 找不到 Java CLASSPATH 和连接器 J

java - 如何为每个 GridView 项目赋予不同的背景颜色?