1

我有一个应用程序 A,它调用另一个应用程序 B,它进行一些计算并写入文件 File.txt A 通过多个线程调用 B 的多个实例,每个实例都尝试写入同一个文件 File.txt 实际问题来了:多个线程尝试访问同一个文件,文件访问抛出这是常见的。

我尝试了一种在单例类中使用并发队列的方法,并且 B 的每个实例都添加到队列中,并且此类中的另一个线程负责从队列中取出项目并写入文件 File.txt。队列被同步获取并且写入操作成功。这很好用。

如果队列中有太多线程和太多项目,则文件写入工作但如果由于某种原因我的队列崩溃或突然停止,则所有应该写入文件的信息都会丢失。

如果我在不使用队列的情况下从 B 同步写入文件,那么它会很慢,因为它需要检查文件锁定,但是在 B 立即写入文件之后,丢失数据的可能性较小。

有什么最好的方法或设计来处理这种情况?文件写入完成后我不需要响应。我不能让 B 等待文件写入完成。

异步等待文件写入在这里会有用吗?

4

2 回答 2

1

是否有更好的方法或设计来处理这种情况?

您可以让每个生产者线程写入它自己的滚动文件,而不是对操作进行排队。每 X 秒,生产者移动到新文件,并且一些聚合线程唤醒,读取(每个生产者的)以前的文件并将结果写入最终File.txt输出文件。这里不需要读/写锁。

这确保了安全恢复,因为滚动文件在您处理和删除它们之前一直存在。

这也意味着你总是写入磁盘,这比在内存中排队任务和批量写入磁盘要慢得多。但这就是你为一致性付出的代价。

异步等待文件写入在这里会有用吗?

使用异步IO与此无关。您提到的问题是 1)共享资源(输出文件)和 2)缺乏一致性(当队列崩溃时),这些都不是异步编程的。

为什么 async 在图片中是因为我不想因为这个文件写入操作而延迟 B 的现有工作

async 确实会帮助你。无论您选择实现什么模式(以解决原始问题),它始终可以通过仅使用异步 IO api 来实现异步。

于 2017-01-10T20:51:07.430 回答
1

我认为你所做的是可以做到的最好的。如果仍然存在问题,您可能需要调整您的生产者/消费者队列解决方案,但在我看来,您使用这种方法做得相当好。

如果内存队列不是答案,那么将其外部化到消息队列和侦听器池可能会有所改进。

关系数据库和事务管理器就是为了解决这个问题而诞生的。为什么继续使用基于文件的解决方案?是否有可能探索替代方案?

于 2017-01-09T14:17:27.220 回答