java—避免线程交错

wbgh16ku  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(262)

我有这个方法:

GenericDatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<GenericRecord>(schema); 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
BinaryEncoder encoder = EncoderFactory.get().binaryEncoder(baos, null);

public void WriteToFile(Record record) {

    this.baos.reset();
    try (FileOutputStream fileOut = new FileOutputStream(avroFile, true)) {
        datumWriter.write(record, encoder);
        encoder.flush();
        fileOut.write("RecordStart\n".getBytes());
        baos.writeTo(fileOut);
        fileOut.write("\nRecordEnd\n".getBytes());
        this.baos.flush();
    } catch (IOException e) {
        logger.error("Error while writing: ", e);
    }
}

上面的方法由多个线程调用,每个线程将编写一个 record 介于 RecordStart 以及 RecordEnd ,可能会发生日志交错的情况,即我们将无法在 RecordStart 以及 RecordEnd 所以要避免这种情况,一个解决办法就是 synchronized 但这将导致性能问题,因为我们正在使线程等待。
所以我想要一些建议,这样我们就可以避免多个线程同时写入同一个文件,这可能会导致日志的交错?

mnemlml8

mnemlml81#

只有当您的操作可以并行化时,您才能从并行处理中获益。我的意思是:
如果您正在写入一个文件,这个特定的计算步骤必须同步完成,即通过 synchronized 或者通过文件锁,否则你会得到混乱的数据。
要提高性能,您可以做的是:尽可能减少同步/锁定块,将最后一步(写入)仅保留在同步或锁定块上。除此之外,您可以写入多个文件。
我更喜欢使用文件锁,因为它将使方法更通用。如果你决定扩展它,这样它就可以用来写多个文件。同时它也避免了其他进程使用文件(除了您的程序)。
看看这个问题。
回答具体问题:
所以我想要一些建议,这样我们就可以避免多个线程同时写入同一个文件,这可能会导致日志的交错?
在不损失性能的情况下。。。我认为没有办法。写入文件的本质要求它是连续的。
我见过的大多数系统都将所有日志写入一个文件,它们使用一个队列和一种方法,在队列可以提供的情况下,一条记录一条记录地写入,因此只要系统不不断地接收超过磁盘所能管理的记录数,所有内容最终都会被写入。

相关问题