Java 向文本文件读/写优先级队列的有效方法是什么?

Java 向文本文件读/写优先级队列的有效方法是什么?,java,data-structures,file-io,Java,Data Structures,File Io,我用Java实现了一个优先级队列类,因为它是一个队列数组。我需要一种很好的方法(不使用序列化)在优先级队列中的对象的每个“事务”或enqueue()/dequeue()之后记录和存储优先级队列的内容。当程序需要从文本文件重建优先级队列时,它应作为备份 我的一些想法和我的问题: 在每个“事务”之后,循环遍历队列,并使用对象之间的分隔符将每个队列写入文件中的一行。 --我的问题是,这将需要对所有对象进行排队和重新排队,这似乎效率很低 每次排队或出列后,只需写入该对象或从文件中删除该对象。 --我的

我用Java实现了一个优先级队列类,因为它是一个队列数组。我需要一种很好的方法(不使用序列化)在优先级队列中的对象的每个“事务”或enqueue()/dequeue()之后记录和存储优先级队列的内容。当程序需要从文本文件重建优先级队列时,它应作为备份

我的一些想法和我的问题:

  • 在每个“事务”之后,循环遍历队列,并使用对象之间的分隔符将每个队列写入文件中的一行。 --我的问题是,这将需要对所有对象进行排队和重新排队,这似乎效率很低

  • 每次排队或出列后,只需写入该对象或从文件中删除该对象。 --我的问题是:如果这是我应该采取的方法,我很难想出一种方法,在退出队列后轻松查找和删除对象


如有任何提示/提示/建议,将不胜感激

要在队列中循环,只需对其进行迭代即可。这是非破坏性的(但只是松散的线程安全)

每次将队列的内容写入磁盘可能非常慢。对于一个典型的硬盘驱动器,一个小的队列大约需要20毫秒才能写入。i、 每秒最多50次。如果您使用SSD,对于一个小队列,这将快得多,但是即使您不使用序列化,您仍然必须封送数据


另一种方法是使用JMS服务器,该服务器旨在支持事务、队列和持久性。一个典型的JMS服务器每秒可以处理大约10000条消息。有很多好的免费服务器可用。

要想在第二种方法中轻松找到对象,我有几个建议:

  • 您可以使用优先级函数在文件中对对象进行排序
  • 要在不同位置管理新添加的对象,请在文本文件中的每个插入对象之间保留一些空间。插入对象时,可以使用类似指针的行为来指定偏移量或其他易于管理的内容
  • 使用缓冲区,因为每次写入内容可能非常慢
  • 如果您仔细使用优先级函数,删除将是微不足道的
  • 此外,在指针指向的小存储桶中进行排序将非常快,您可以通过在一段时间后压缩所有对象来始终使用垃圾收集类型的行为
    我将以日志模式实现您的需求。在文件末尾,追加每个排队及其优先级,追加每个出列。如果您的消息服务器崩溃,您可以重播日志文件,并以相应的状态结束

    显然,随着时间的推移,日志文件将变得越来越大。为了解决这个问题,您需要每隔一段时间轮换一次日志文件。为此,请在某个时间点序列化队列,然后开始登录新文件。在将数据结构的快照写入磁盘时,您甚至可以在不锁定状态(冻结queu请求)的情况下完成此操作,方法是同时将事务记录到新旧日志中。快照完成后,将指示该快照的指针写入磁盘,您可以删除旧日志

    写时间和空间是N,重放应该是罕见的,而且比较快。

    一个建议:(考虑是否使用一个文件不是必须的):

    如果对象编号不是很大,请将每个对象存储到单独的文件中。当然,您需要为每个对象创建一个唯一的标识符,您也可以使用该标识符作为文件名。这样,您总是根据存储在对象中的标识符添加或删除单个文件。如果对象属于各种不能修改的类,则只需存储一个将标识符映射到对象的hashmap即可。因此,在将对象添加到队列之前,先创建一个标识符,然后将对象和标识符成对添加到映射中,然后编写一个新文件名作为标识符并包含该对象。我在删除和重新加载时留下了要做的事情,因为这只不过是练习而已


    就我个人而言,我赞成罗伯特·哈维在对这个问题的评论中提出的建议。考虑数据库的使用,特别是如果您的项目已经有一个数据库的话。这将使存储对象和删除对象比在文件中定位位置更容易、更快。因为即使在文件中找到了对象的位置,也很可能需要再次写入整个文件(仅在没有该对象的情况下)。这与循环没有什么不同。使用数据库可以避免所有这些麻烦

    我想我必须问一下,因为有人无论如何都会这样做,但是序列化和反序列化有什么问题吗?这是一个性能问题吗?如果是的话,它实际上已经成为一个性能问题了吗?您能为您的优先级队列显示代码吗?因为这不意味着要求所有要序列化的类都必须实现可序列化吗?此外,数据持久性也会成为一个问题,因为如果类稍微更改,序列化将无法再加载过时的记录。如果您可以确保每个对象占用固定数量的行,为什么不根据行号查找它呢?但是如果您在每次更改后持久化此队列,以及任何较大的队列,你需要一个比一个文本文件更有马力的东西。您的应用程序是否使用数据库?为什么不将其存储在那里呢?迭代器不必按元素的优先级顺序遍历元素。它不需要按任何顺序保存它们。当您将它们加载到优先级队列中时,它的行为方式仍然相同。