java - 阻塞队列的实现

标签 java thread-safety blockingqueue

我刚刚实现了一个带有信号量的自定义阻塞队列。

由于我找不到的原因,当我的队列为空时,我的队列不会被信号量阻塞。

这是我的实现:

package poolThread;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.Semaphore;

public class MyQueue<E> {
Semaphore s = new Semaphore(0, true);
private Queue<E> queue = new LinkedList<E>(); 


public boolean isEmpty(){
    return this.queue.isEmpty();
}
public void enqueue(E e){
    queue.add(e);
    s.release();
}
public E dequeue(){
    E e = null;
    try {
        s.acquire();
    } catch (InterruptedException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    e = queue.remove();
    return e;

}

}

你能帮我找出代码中的错误吗?

最佳答案

这里的问题是 LinkedList - 它不是线程安全的。因此,即使正确获取了许可,LinkedList 上的 remove() 操作也可能(并且将会)引起麻烦。这是一个简单的“测试用例”来显示行为:

MyQueue<String> x = new MyQueue<>();

ExecutorService es = Executors.newFixedThreadPool(2);
for (int j = 0; j < 2; j++)
    es.submit(() -> {
        String tn = Thread.currentThread().getName();
        for (int i = 0; i < 2; i++)
            x.enqueue("v" + i);

        for (int i = 0; i < 2; i++) 
            System.out.println(tn + " deq: " + x.dequeue());
    });

输出将类似于(由于 remove 方法上的 NoSuchElementException,您将看到 null):

pool-1-thread-2 deq: v0
pool-1-thread-1 deq: null

最简单的解决方案是将您的 LinkedList 替换为 java.util.concurrent.ConcurrentLinkedQueue

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

相关文章:

Java - 单线程执行器

c++ - 在访问工作线程的 lambda 中捕获的 vector 列表中的元素的引用时,是否需要互斥锁?

java - 如果多个 JVM 或容器访问共享内存,如何在 Java 中实现线程安全?

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

java - LinkedBlockingQueue 在生产者-消费者场景中具有许多生产者的线程安全性

java - 在多线程编程中使用静态类方法

Java字符串停止转义字符 Action

java - TODO-FIXME : In Java 8's Integer class?

java - RESTful Web 服务中的 URL 是否可以为具有不同授权级别的用户执行不同的操作?

java - SQLJ VS JAVA 文件