Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:每隔几秒钟创建一次文件_Java_Multithreading_File Io_Concurrency_Thread Safety - Fatal编程技术网

Java:每隔几秒钟创建一次文件

Java:每隔几秒钟创建一次文件,java,multithreading,file-io,concurrency,thread-safety,Java,Multithreading,File Io,Concurrency,Thread Safety,我正在使用ScheduledThreadPoolExecutor每隔fileIntervalInSeconds创建一个文件: executorService = new ScheduledThreadPoolExecutor(1); executorService.scheduleAtFixedRate(new Runnable() { @Override public void run()

我正在使用ScheduledThreadPoolExecutor每隔fileIntervalInSeconds创建一个文件:

executorService = new ScheduledThreadPoolExecutor(1);
        executorService.scheduleAtFixedRate(new Runnable()
        {
            @Override
            public void run()
            {
                    File file = new File(fileName);
                    if (file.exists())
                    {
                        Log.debug("creating new file");
                        openFileWriter(file);
                    }

            }
        }, fileIntervalInSeconds, fileIntervalInSeconds, TimeUnit.SECONDS);
    }
private void openFileWriter() throws FileSystemNotificationException
{

        // 1 - close exist writer
        writer.close();
        // 2 - rename to backup file name
          ...
        // 3 - create new file      
        FileWriter writerFile = new FileWriter(fileName, true);
        writer = new PrintWriter(writerFile);

}
我一直在向文件中写入警告消息:

private synchronized void writeLine(String line) throws InterruptedException
{
    writer.println(line);
}
我的问题是:

  • 当writer未关闭时,如何确保我正在使用它?(writer.close())
  • 在开始写入之前,如何等待ScheduledThreadPoolExecutor完成文件的创建

  • 在写入文件之前检查文件是否存在如何。不需要反向绑定线程或同步

    private synchronized void writeLine(String line) {
        if (!file.exists())
           reopenWritingFile();
        writer.println(line);
    }
    

    你有两个选择:

  • 在关闭旧编写器之前创建新编写器
  • 在关闭编写器之前建立一个锁,在编写时检查该锁
  • 示例:

    volatile PrintWriter writer;
    ReadWriteLock lock = new ReentrantReadWriteLock();
    Lock writeLock = lock.writeLock();
    Lock readLock = lock.readLock();
    
    private void openFileWriterWithLock() throws IOException {
    
      if (writeLock.tryLock()) {
        try {
          // 1 - close exist writer
          writer.close();
          // 2 - rename to backup file name
          //...
          // 3 - create new file      
          FileWriter writerFile = new FileWriter(fileName, true);
          writer = new PrintWriter(writerFile);
        } finally {
          writeLock.unlock();
        }
      }
    
    }
    
    private synchronized void writeLineWithLock(String line) throws InterruptedException {
      readLock.lock();
      try {
        writer.println(line);
      } finally {
        readLock.unlock();
      }
    }
    
    private void openFileWriterWithoutLock() throws IOException {
      // 0. Note old file.
      PrintWriter oldWriter = writer;
      // 1. Create new file.
      FileWriter writerFile = new FileWriter(fileName, true);
      // 2. Swap the new one in.
      writer = new PrintWriter(writerFile);
      // 3 - close old writer
      oldWriter.close();
    }
    
    private synchronized void writeLineWithoutLock(String line) throws InterruptedException {
      writer.println(line);
    }
    

    您可以在write方法中每小时创建一个新文件。您可能会有一些轻微的时间检查开销,但这应该可以忽略不计。下面的示例将每小时创建一个新的日志文件,并在文件名前面添加以毫秒为单位的时间。您可以根据自己的情况设置时间格式

    public class LogWriter {
        private long lastCreationTime;
        PrintWriter writer;
        String logFileName;
    
        public LogWriter(String logFileName) {
            this.logFileName = logFileName;
            createLogFile(logFileName);
        }
    
        private void createLogFile(String fileName) {
            if(writer != null) {
                writer.close();
            }
            lastCreationTime = System.currentTimeMillis();
            FileWriter writerFile;
            try {
                writerFile = new FileWriter(lastCreationTime + "_" + fileName, true);
                writer = new PrintWriter(writerFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
        private synchronized void writeLine(String line) {
            if(lastCreationTime < System.currentTimeMillis() - 3600000) {
                createLogFile(logFileName);
            }
            writer.write(line);
        }
    }
    
    公共类日志编写器{
    私人长时间创作;
    版画作家;
    字符串日志文件名;
    公共日志编写器(字符串日志文件名){
    this.logFileName=logFileName;
    创建日志文件(日志文件名);
    }
    私有void createLogFile(字符串文件名){
    if(writer!=null){
    writer.close();
    }
    lastCreationTime=System.currentTimeMillis();
    文件编写器写入文件;
    试一试{
    writerFile=新文件编写器(lastCreationTime+“”+文件名,true);
    writer=新的PrintWriter(writerFile);
    }捕获(IOE异常){
    e、 printStackTrace();
    }
    }
    专用同步无效写入线(字符串行){
    如果(lastCreationTime
    让一个单独的线程来处理日志记录,而不是那个相当复杂的构造,怎么样

    public class Logger extends Thread {
    
    private final LinkedBlockingQueue<String> linesToWrite = new LinkedBlockingQueue<>();
    private final String filename;
    
    private Logger(String filename) {
      super("Logging thread");
      this.filename = filename;
      this.setDaemon(true);
      this.setPriority(Thread.MIN_PRIORITY);
    }
    
    @Override
    public void run() {
      try (BufferedWriter out = new BufferedWriter(new FileWriter(filename, true))) {
    
        String line;
        while (this.isInterrupted() == false) {
          line = linesToWrite.take();
          out.write(line);
          out.newLine();
          out.flush();
        }
      } catch (InterruptedException e) {
      } catch (IOException ex) {
        System.out.println("Failed to access log file: " + ex);
      }
    }
    
    public void log(final String line) {
      this.linesToWrite.add(line);
    }
    
    然后,您可以在任何地方以线程安全的方式使用它,如下所示:

    logger.log("Test message");
    
    logger.interrupt();
    
    您不需要停止记录器,因为Java将使用try构造确保文件正确关闭。但是,如果您愿意,可以这样停止:

    logger.log("Test message");
    
    logger.interrupt();
    

    现在,您可以通过单线程方式执行所有文件操作,因为任何时候都只有一个线程访问日志文件。

    像logback这样的日志框架可以为您完成所有这一切,开箱即用是,但logback不知道每1小时创建一个文件,甚至没有人写入它-空文件你说得对,但我如何知道我的对象PrintWriter是否未关闭?我不想丢失这一行,我想把它写到文件中,如果你关闭了它,文件只会被关闭。除了单元测试之外,我不会关闭该文件,而是继续刷新输出。如果您想知道PrintWriter是否出错,可以检查PrintWriter.checkError(),或者可以使用BufferedWriter,它会引发IOException。是的,但我希望每1小时创建一个文件,即使没有人写入它-空file@user2143023-如果没有人对文件进行写入,则会使文件保持打开状态超过一小时,但一旦有人这样做,它就会创造一个新的。你永远不会在一个文件中写入超过一小时的数据。