我正在尝试使用多个线程在 Java 中编写一个大文件。
我都尝试过FileWriter
and bufferedWriter
Java 中的类。
正在写入的内容实际上是使用读取的整个表(Postgres)CopyManager
并写下。文件中的每一行都是表中的一个元组,我一次写入 100 行。
写法:
单个待写入文件由多个线程以追加模式打开。
此后每个线程尝试写入文件 file。
以下是我面临的问题:
- 有时,文件的内容会被覆盖,即:一行仍然不完整,下一行从那里开始。我的假设是 writer 的缓冲区已满。这迫使写入者立即将数据写入文件。写入的数据可能不是完整的行,在写入剩余部分之前,下一个线程会将其内容写入文件。
- 使用时
Filewriter
,有时我会在文件中看到一条黑线。
有什么建议,如何避免此数据完整性问题?
共享资源==争用
根据定义,写入普通文件是一个序列化操作。尝试从多个线程写入数据不会获得任何性能,I/O 是一种有限的有限资源,其带宽甚至比最慢或最过载的 CPU 还要小几个数量级。
对共享资源的并发访问可能很复杂(而且很慢)
如果您有多个线程正在执行昂贵的计算,那么您就有选择,如果您只是因为认为要加快速度而使用多个线程,那么您只会做相反的事情。 I/O 争用总是会减慢对资源的访问速度,但由于锁等待和其他开销,它永远不会加快速度。
您必须有一个受保护的关键部分,并且一次只允许一个写入者。只需查找支持并发的任何日志编写器的源代码,您就会发现只有一个线程写入文件。
如果您的应用主要是:
-
CPU 限制:您可以使用某种锁定机制/数据构造来一次只让多个线程中的一个线程写入文件,从并发的角度来看,作为一种幼稚的解决方案,这将是无用的;如果这些线程受 CPU 限制且 I/O 很少,那么这可能会起作用。
-
I/O 限制:这是最常见的情况,您必须使用带有某种队列的消息传递系统,并将所有线程发布到队列/缓冲区,并从其中提取单个线程并写入文件。这将是最具可扩展性和最容易实施的解决方案。
日志记录 - 异步写入
如果您需要创建一个超大文件,其中写入顺序并不重要并且程序受 CPU 限制,您可以使用日志技术。
各有process
写入一个单独的文件,然后最后将多个文件连接成一个大文件。这是一所非常古老的学校low tech效果良好且已经使用了数十年的解决方案。
显然,您拥有的存储 I/O 越多,最终连接的性能就越好。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)