flo*_*wer 1 java multithreading java.util.concurrent java-8 threadpoolexecutor
首先我创建了一个空文件,然后我调用了一些线程来搜索数据库并获取结果内容,然后附加到文件中。结果内容为Stringtype,可能为20M。每个线程应该一次写入一个文件。我测试了很多次,我发现没有必要锁定。那正确吗?例子总共1000行,什么时候需要加写锁对文件进行操作?
    String currentName = "test.txt";
    final String LINE_SEPARATOR = System.getProperty("line.separator");
    ThreadPoolExecutor pool = new ThreadPoolExecutor(
            10, 100, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
    for (int i = 0; i < 500; i++) {
        pool.execute(() -> {
            try {
                appendFileByFilesWrite(currentName, "abc" +
                        ThreadLocalRandom.current().nextInt(1000) + LINE_SEPARATOR);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }
    IntStream.range(0, 500).<Runnable>mapToObj(a -> () -> {
        try {
            appendFileByFilesWrite( currentName,
                    "def" + ThreadLocalRandom.current().nextInt(1000) +
                    LINE_SEPARATOR);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }).forEach(pool::execute);
    pool.shutdown(); 
这是方法:
public static void appendFileByFilesWrite(String fileName,String fileContent) throws IOException {
    Files.write(Paths.get(fileName), fileContent.getBytes(),StandardOpenOption.APPEND);
}
答案是:总是。
你的测试对你有用。马上。今天。也许在满月期间,它不会。也许如果你买了一台新电脑,或者你的操作系统供应商更新,或者 JDK 更新,或者你在你的 winamp 中播放布兰妮斯皮尔斯的歌曲,它不会。
规范说写入在多个步骤中被涂抹是合法的,并且此时 SOO.APPEND 的行为是未定义的。可能如果您同时编写“Hello”和“World”,文件最终可能包含“HelWorllod”。它可能不会。但它可以。
通常,并发中的错误很难(有时几乎不可能)测试。不会让它成为一个错误;大多数情况下,您最终会收到大量错误报告,并且您对所有报告都回答“无法重现”。这不是一个好地方。
如果您想观察实际问题,很可能应该在编写器中编写极长的字符串;目的是最终得到涉及多个分离出的块的实际低级磁盘命令。即使那样,也不能保证您会观察到问题。然而,没有证据并不是没有证据。