我有几十个生产者和一个单一消费者的情景。时机至关重要:出于性能原因,我想避免任何生产者锁定,我希望消费者在没有消息准备好的情况下尽可能少地等待。
我已经开始使用ConcurrentLinkedQueue了,但是我不想在sleep
时给消费者打电话queue.poll() == null
,因为我可能会浪费宝贵的毫秒数,而且我不会这样做。我想使用yield
,因为我最终浪费了cpu。
所以我开始实现一种ConcurrentBlockingQueue,以便消费者可以运行类似的东西:
T item = queue.poll();
if(item == null) {
wait();
item = queue.poll();
}
return item;
和制片人一样:
queue.offer(item);
notify();
不幸的是,wait / notify仅适用于synchronized块,这反过来会大大降低生产者的性能。 是否还有其他不需要同步的等待/通知机制实现?
我知道没有等待和通知已同步的风险,我设法通过运行以下内容的外部线程解决它们:
while(true) {
notify();
sleep(100);
}
答案 0 :(得分:3)
我已开始使用
时,我不想给消费者打电话。ConcurrentLinkedQueue
,但在queue.poll() == null
您应该检查the BlockingQueue
interface,其中take
方法会阻止,直到某个项目可用为止。
它有几个实现,详见javadoc,但ConcurrentLinkedQueue
不是其中之一:
所有已知的实施课程:
ArrayBlockingQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, LinkedTransferQueue, PriorityBlockingQueue, SynchronousQueue
答案 1 :(得分:0)
我推出了以下实现:
private final ConcurrentLinkedQueue<T> queue = new ConcurrentLinkedQueue<>();
private final Semaphore semaphore = new Semaphore(0);
private int size;
public void offer(T item) {
size += 1;
queue.offer(item);
semaphore.release();
}
public T poll(long timeout, TimeUnit unit) {
semaphore.drainPermits();
T item = queue.poll();
if (item == null) {
try {
semaphore.tryAcquire(timeout, unit);
} catch (InterruptedException ex) {
}
item = queue.poll();
}
if (item == null) {
size = 0;
} else {
size = Math.max(0, size - 1);
}
return item;
}
/** An inaccurate representation O(1)-access of queue size. */
public int size() {
return size;
}
具有以下属性:
BlockingQueue
中使用Lock
的{{1}}实现,或使用wait / notify的同步块实现offer()
,没有sleep
)jdk中有没有我不知道的等效实现?开放批评。