【问题标题】:Are regular Queues inappropriate to use when multithreading in Java?在 Java 中进行多线程时,是否不适合使用常规队列?
【发布时间】:2011-12-07 09:14:37
【问题描述】:

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

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

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

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

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

我想知道是否可以为此任务使用常规队列,或者我是否需要更专用的东西,例如 this question 中讨论的队列。

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

使用更专业的队列是否有优势无论如何

【问题讨论】:

    标签: java multithreading queue


    【解决方案1】:

    是的,普通的Queue 是不合适的。由于您有两个线程,因此您需要担心边界条件,例如空队列、满队列(假设您出于内存考虑需要对其进行绑定)或可见性等异常情况。

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

    【讨论】:

      【解决方案2】:

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

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

      ...

      BlockingQueue 实现主要用于 生产者-消费者队列,但另外支持Collection 界面。

      ...

      BlockingQueue 实现是线程安全的。

      只要您已经在分析您的代码,请尝试将BlockingQueue 放入其中,看看会发生什么!

      祝你好运!

      【讨论】:

      • 啊,是的,对于@Tim,LinkedBlockingQueue 就是其中之一。 BlockingQueueLinkedBlockingQueue 实现的接口。
      【解决方案3】:

      我认为这并不重要。

      如果您在内存中序列化一个状态有 25% 的开销,那么它仍然会与队列一起存在。 磁盘会更贵。 相比之下,队列阻塞机制会很便宜。

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

      【讨论】:

        猜你喜欢
        • 2014-10-13
        • 1970-01-01
        • 2013-08-01
        • 2014-05-12
        • 1970-01-01
        • 2012-03-25
        • 1970-01-01
        • 1970-01-01
        • 2016-09-19
        相关资源
        最近更新 更多