简体   繁体   English

没有同步的Java等待/通知实现

[英]Java wait/notify implementation without synchronized

I have a scenario with dozens of producer and one single consumer. 我有几十个生产者和一个单一消费者的情景。 Timing is critical: for performance reason I want to avoid any locking of producers and I want the consumer to wait as little as possible when no messages are ready. 时机至关重要:出于性能原因,我想避免生产者的任何锁定,我希望消费者在没有消息准备就绪时尽可能少地等待。

I've started using a ConcurrentLinkedQueue, but I don't like to call sleep on the consumer when queue.poll() == null because I could waste precious milliseconds, and I don't want to use yield because I end up wasting cpu. 我已经开始使用ConcurrentLinkedQueue了,但是当queue.poll() == null时我不喜欢在使用者queue.poll() == null调用sleep ,因为我可能浪费宝贵的毫秒数,而且我不想使用yield因为我最终浪费了中央处理器。

So I came to implement a sort of ConcurrentBlockingQueue so that the consumer can run something like: 所以我来实现一种ConcurrentBlockingQueue,以便消费者可以运行如下:

T item = queue.poll();
if(item == null) {
    wait();
    item = queue.poll();
}
return item;

And producer something like: 和制片人一样:

queue.offer(item);
notify();

Unfortunately wait/notify only works on synchronized block, which in turn would drastically reduce producer performance. 不幸的是,wait / notify仅适用于synchronized块,这反过来会大大降低生产者的性能。 Is there any other implementation of wait/notify mechanism that does not require synchronization? 是否还有其他不需要同步的等待/通知机制实现?

I am aware of the risks related to not having wait and notify synchronized, and I managed to resolve them by having an external thread running the following: 我知道没有等待和通知同步的风险,我设法通过运行以下的外部线程来解决它们:

while(true) {
    notify();
    sleep(100);
}

I've started using a ConcurrentLinkedQueue , but I don't like to call sleep on the consumer when queue.poll() == null 我已经开始使用ConcurrentLinkedQueue ,但是当queue.poll() == null时我不喜欢在使用者queue.poll() == null调用sleep

You should check the BlockingQueue interface , which has a take method that blocks until an item becomes available. 您应该检查BlockingQueue接口 ,该接口具有阻塞直到项目可用的take方法。

It has several implementations as detailed in the javadoc, but ConcurrentLinkedQueue is not one of them: 它有几个实现,详见javadoc,但ConcurrentLinkedQueue不是其中之一:

All Known Implementing Classes: 所有已知的实现类:
ArrayBlockingQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, LinkedTransferQueue, PriorityBlockingQueue, SynchronousQueue

I came out with the following implementation: 我出来了以下实现:

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

With the following properties: 具有以下属性:

  • producers never go to SLEEP state (which I think can go with BlockingQueue implementations that use Lock in offer() , or with synchronized blocks using wait/notify) 生产者永远不会进入SLEEP状态(我认为可以使用在offer()中使用Lock BlockingQueue实现,或者使用wait / notify的synchronized块)
  • consumer only goes to SLEEP state when queue is empty but it is soon woken up whenever a producer offer an item (no fixed-time sleep , no yield ) 当队列为空时,消费者只进入睡眠状态,但只要生产者提供物品,它就会很快被唤醒(没有固定时间的sleep ,没有yield
  • consumer can be sometime woken up even with empty queue, but it's ok here to waste some cpu cycle 即使有空的队列,消费者也可能有时被唤醒,但这里可以浪费一些cpu周期

Is there any equivalent implementation in jdk that I'm not aware of? 在jdk中是否有任何我不知道的等效实现? Open for criticism. 开放批评。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM