带有 isEmpty() 更改通知的队列
我在生产者-消费者环境中有一个 BlockingQueue
(取自 ScheduledThreadPoolExecutor
)。有一个线程将任务添加到队列中,还有一个线程池执行它们。
我需要有关两个事件的通知:
- 第一个项目添加到空队列
- 最后一个项目从队列中删除
通知 = 将消息写入数据库。
有什么明智的方法来实现这一点吗?
I have an BlockingQueue<Runnable>
(taken from ScheduledThreadPoolExecutor
) in producer-consumer environment. There is one thread adding tasks to the queue, and a thread pool executing them.
I need notifications on two events:
- First item added to empty queue
- Last item removed from queue
Notification = writing a message to database.
Is there any sensible way to implement that?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一种简单而幼稚的方法是使用一个实现来装饰您的 BlockingQueue,该实现只需检查底层队列,然后发布一个任务来执行通知。
但这种方法有几个问题。而空-> notEmpty 非常简单 - 特别是对于单个生产者的情况,两个消费者很容易同时运行并且都看到队列从非空 -> 。空的。
但是,如果您想要的只是通知队列在某个时间变空,那么只要您的通知者是您的状态机,跟踪空和非空并在何时通知就足够了它从一个变为另一个:
现在这是围绕实际通知程序实现的线程安全防护,可能将任务发送到执行程序以将事件异步写入数据库。
A simple and naïve approach would be to decorate your BlockingQueue with an implementation that simply checks the underlying queue and then posts a task to do the notification.
This approach though has a couple of problems. While the empty -> notEmpty is pretty straightforward – particularly for a single producer case, it would be easy for two consumers to run concurrently and both see the queue go from non-empty -> empty.
If though, all you want is to be notified that the queue became empty at some time, then this will be enough as long as your notifier is your state machine, tracking emptiness and non-emptiness and notifying when it changes from one to the other:
This is now a thread-safe guard around an actual Notifier implementation that perhaps posts tasks to an Executor to asynchronously write the events to the database.
该设计很可能有缺陷,但您可以相对简单地做到这一点:
您有一个单线程添加,因此您可以在添加之前进行检查。即 pool.getQueue().isEmpty() - 只有一个生产者,这是安全的。
无法保证最后删除的项目,但您可以覆盖
beforeExecute
并再次检查队列。在isEmpty()
返回 true 后可能会有一个小超时。也许下面的代码在 afterExecute 中执行会更好。有时
我可以解释为什么使用队列本身进行通知不能很好地工作:假设您添加一个要由池执行的任务,该任务立即计划,队列再次为空,您将需要通知。
The design is most likely flawed but you can do it relatively simple:
You have a single thread adding, so you can check before adding. i.e.
pool.getQueue().isEmpty()
- w/ one producer, this is safe.Last item removed cannot be guaranteed but you can override
beforeExecute
and check the queue again. Possibly w/ a small timeout afterisEmpty()
returns true. Probably the code below will be better off executed in afterExecute instead.sometime like that
I can explain why doing notifications w/ the queue itself won't work well: imagine you add a task to be executed by the pool, the task is scheduled immediately, the queue is empty again and you will need notification.