阻塞队列实现

时间:2016-05-04 19:32:36

标签: 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;

}

}

你可以帮我在代码中找到错误吗?

1 个答案:

答案 0 :(得分:2)

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

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());
    });

输出类似于(由null方法NoSuchElementException s引起的remove}:

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

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