常规队列是否不适合在Java中多线程时使用?



我正在尝试添加异步输出到我的程序。

目前,我有一个eventManager类,得到通知的每一帧的位置的任何可移动的对象目前存在于主循环(它渲染一个场景;有些对象随着帧的变化而变化,有些对象是静态的,并且在每一帧中都存在)。我希望记录下每一帧的状态,这样我就可以添加回放场景的功能。

这意味着我需要从一帧到另一帧存储变化的信息,并将其保存在内存中或写入磁盘以供以后检索和解析。

我做了一些计时实验,将每个对象的状态记录到内存中使每帧时间增加了大约25%(更不用说最终达到内存限制的可能性)。直接将每个帧写入磁盘所需的时间(可以预见)甚至更长,几乎是根本不记录帧所需时间的两倍。

不用说,我想实现多线程,这样我就不会在我的主渲染循环中每秒丢失帧数,因为进程不断写入磁盘。

我想知道是否可以使用常规队列来完成这个任务,或者我是否需要像这个问题中讨论的队列那样更专用的东西。

在我的情况下,只有一个生产者(主线程)和一个消费者(我想异步写入磁盘的线程)。生产者永远不会从队列中删除,消费者也永远不会添加到队列中——所以我需要一个专门的队列吗?

使用更专门化的队列是否有优势?

是的,常规的Queue是不合适的。因为你有两个线程,你需要担心边界条件,如空队列,满队列(假设你需要绑定它的内存考虑),或异常,如可见性。

LinkedBlockingQueue最适合您的应用。puttake方法使用不同的锁,因此不会出现锁争用。take方法将自动阻止消费者写入磁盘,如果它以某种方式神奇地赶上了生产者渲染帧。

听起来好像您不需要一个特殊的队列,但是如果您希望从队列中删除的线程等待,直到有东西可以获得,请尝试BlockingQueue。它在java.util.concurrent包中,所以它肯定是线程安全的。以下是该页中的一些相关引用:

额外支持等待队列操作的Queue在检索元素时变为非空,并等待空间变为空在存储元素时在队列中可用。

BlockingQueue实现主要用于生产者-消费者队列,但额外支持Collection接口。

BlockingQueue实现是线程安全的。

只要你已经分析了你的代码,试着在那里放一个BlockingQueue,看看会发生什么!

祝你好运!

我认为这没什么大不了的。

如果在内存中序列化状态有25%的开销,那么队列仍然存在。磁盘将更加昂贵。相比之下,队列阻塞机制将是便宜的。

需要注意的一件事是您的队列增长失控:磁盘无论如何都很慢,如果它不能足够快地消耗队列事件,您就有麻烦了。

最新更新