线程安全地写入同一文件

时间:2018-09-07 20:38:41

标签: java multithreading

我创建了此方法,以通过多个线程将文本写入同一文件:

public static void ThreadsafeWriter(String text, String file) throws IOException {
    String nodeValue = text;
    BufferedWriter writer = new BufferedWriter(new FileWriter(file, true));
    synchronized (writer) {
        String[] words = nodeValue.split(" ");
        for (String word: words) {
            writer.write(word);
            writer.newLine();
        }
        writer.close();
    }
}

我想问一下它是否有任何错误,是否会导致异常?

谢谢!

2 个答案:

答案 0 :(得分:2)

您的synchronized块不会执行任何操作;这不是线程安全的。

同步是基于每个实例的:synchronized (writer)表示没有其他监视器可以在相同的完全相同的writer实例上输入同步块。但是,您只是在您的方法中创建了该编写器,并且从未将其发布到另一个线程。没有其他线程会看到该对象,更不用说尝试在该对象上输入同步块了。

您需要创建从文件路径到要锁定的对象的静态映射之类的东西(并注意别名等,它们可能具有不同的路径,但引用相同的文件)。当然,这些都不会阻止另一个进程将其写入文件。

文件的原子性很棘手。一种常见的技术是写入一个临时的随机文件,然后将该文件移到目标路径。

答案 1 :(得分:0)

您可以通过不使用org.apache.sling.commons.log.file="SampleProject.log" org.apache.sling.commons.log.level="info" org.apache.sling.commons.log.logger.paatern ="org.wc.project" org.apache.sling.commons.log.pattern="{0,date,dd.MM.yyyy HH:mm:ss.SSS} *{4}* [{2}] {3} {5}" 变量,而使用另一个writer变量进行同步来实现。这样,所有调用此方法的对象将使用同一对象进行同步,而不是每个调用都在创建新的BufferedWriter。

示例:

static

编辑:对不起,我只是重新阅读了您的问题。考虑到我要尝试写入的文件在两次调用之间是相同还是不同,因此我的“修复”确实会忽略。只是使其“不可能”在“相同时间”写入两个文件。