繁体   English   中英

如何从多个线程输出到 .txt 文件?

[英]How do I output from multiple threads to a .txt file?

这是我当前的线程,我用它来对 CPU 进行压力测试,我需要每小时将“Hcount”输出到一个 .txt 文件中,目前,它会打印它,但只能从一个线程打印,当另一个小时过去时,它会删除什么写在 .txt 文件上并重写新的“Hcount”我正在运行 3 个线程。

import java.util.Random;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class MyThread extends Thread{
    public void run() {
        String B;//Will hold the value of Cpointer
        String A;//will hold the string value of Hcount
        Path fileName =
                Path.of("D:/EEoutput/Out.txt");
        Random rand = new Random();
        long Hcount = 0;//counts the number of iterations in an hour
        long t = System.currentTimeMillis();
        long end = t + 3800000*5;//a minute
        double a1 = 0; //random holder 1
        double a2 = 0;//random holder 2
        double answer = 0; // answer placeholder
        Long hour = System.currentTimeMillis()+3600000;//will be used to say when are we outputing the number of iterations to the file
        int Cpointer = 1;//will tell how many hours has passed
        while (System.currentTimeMillis() < end) {
            a1 = rand.nextDouble();
            a2 = rand.nextDouble();
            answer = a1 * 23 / (a2 + a1) + a2;
            Hcount++;
            if (System.currentTimeMillis() >= hour)// checks if the program needs to
            {
                 B = String.valueOf(Cpointer);
                 A=String.valueOf(Hcount);
                try {
                    Files.writeString(fileName, A);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                hour = System.currentTimeMillis()+3600000;//sets stop to next hour
                Cpointer++;//declares that another hour has passed, will be used to tell how many iterations are there in a certain hour
                Hcount = 0;
            }
        }

    }
}
'''

从多个线程写入文件是一个坏主意。 我建议您创建一个队列(即使只是在内存队列中)并让所有线程将他们想要写入文件的信息写入此队列。 换句话说,您的队列将有多个生产者。 而不是在您的队列中有一个消费者将从队列中读取并将其写入您的文件。 这样,您将只有一个线程写入文件

你在这里有两个不同的问题。

  • Files.writeString默认替换内容。 你想要Files.writeString(fileName, A, StandardOpenOption.APPEND)
  • 从同时线程写入同一个文件是行不通的(想想看。操作系统不能保证你的写入是原子的,这应该是显而易见的)。 因此,即使您修复它,它似乎也会起作用,但您经常会失败:竞争条件。

解决最后一部分的通常策略是使用某种锁。 如果单个 JVM 是唯一执行这些文件写入的 JVM,则您可以使用 java 提供的任何您喜欢的东西:例如synchronized 或者来自juconcurrent包的ReadWriteLock

但是,这确实意味着您的 CPU 压力线程将等待锁定。 相反,您可能想要启动一个单独的线程,并拥有一个 ConcurrentBlockingQueue。 您的 CPU 压力测试器将日志消息发送到队列,而您的日志写入器线程将执行 5 行循环:无休止地,从队列中获取一个项目(这会阻塞直到有东西),将其写入文件,刷新流和循环。

鉴于现在只有一个线程写入,这解决了一堆问题。

如果是多个 JVM,那就更棘手了——然后用.lock文件锁定。 您可以使用Files.createFile()创建logfile.lock 如果文件已经存在,这将失败。 然后等待一段时间(你不能让操作系统告诉你文件何时被删除,所以你必须等待半秒左右再检查一遍,永远,直到文件消失),直到它成功,然后写入,然后删除锁定文件。

.lock文件的一个主要缺点是:如果您的进程硬崩溃,锁定文件会一直存在。 你不想要的。 一种解决方案是向其写入您自己的 PID(进程 ID),因此任何进行检查的人至少可以看到它所属的进程已死。 除了这很棘手; 现代操作系统不仅仅让您检查是否存在,而且它都非常依赖于操作系统(据我所知,没有自动化这些东西的 java 库)。 这一切都变得相当复杂,所以,让我们保持简单:

如果您想从同一系统上的不同 JVM / 进程同时写入同一文件,您可以“安全”地执行此操作,但它相当复杂。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM