【问题标题】:Write to text file from multiple threads? [duplicate]从多个线程写入文本文件? [复制]
【发布时间】:2012-04-19 02:23:30
【问题描述】:

我有 20 个线程使用 println() 函数写入一个名为 results.txt 的文件。我怎样才能将它们全部同步?

我注意到每次我的程序运行时,results.txt 中的文本行数都不同。

谢谢。

【问题讨论】:

标签: java multithreading


【解决方案1】:

通过包含synchronized method 的类访问文件以写入文件。一次只有一个线程能够执行该方法。

我认为单例模式适合您的问题:

package com.test.singleton;

public class Singleton {
    private static final Singleton inst= new Singleton();
    
    private Singleton() {
        super();
    }
    
    public synchronized void writeToFile(String str) {
        // Do whatever
    }
    
    public static Singleton getInstance() {
        return inst;
    }
    
}

每次您需要写入文件时,您只需调用:

Singleton.getInstance().writeToFile("Hello!!");

【讨论】:

  • +1 简单但有效。但是,“a class”应该是“an object”(从具有所述同步方法的类实例化),因为synchronized 方法只是每个对象互斥的。
  • @MarcoMicheli 这个答案的重点是:synchronized
  • (技术上是static methods can be synchronized too,但使用静态方法!)
  • 我会使用enum 作为单身人士。
  • getInstance() 方法需要是静态的
【解决方案2】:

重复的问题...重复的答案。 As I said here:

如果您可以将文件保存为FileOutputStream,您可以像这样锁定它:

FileOutputStream file = ...
....
// Thread safe version.
void write(byte[] bytes) {
  try {
    boolean written = false;
    do {
      try {
        // Lock it!
        FileLock lock = file.getChannel().lock();
        try {
          // Write the bytes.
          file.write(bytes);
          written = true;
        } finally {
          // Release the lock.
          lock.release();
        }
      } catch ( OverlappingFileLockException ofle ) {
        try {
          // Wait a bit
          Thread.sleep(0);
        } catch (InterruptedException ex) {
          throw new InterruptedIOException ("Interrupted waiting for a file lock.");
        }
      }
    } while (!written);
  } catch (IOException ex) {
    log.warn("Failed to lock " + fileName, ex);
  }
}

【讨论】:

  • 来自 FileLock 的 JavaDoc:“文件锁代表整个 Java 虚拟机持有。它们不适用于控制同一虚拟机内的多个线程对文件的访问。”
  • @theadam - 这句话后面紧跟 文件锁对象可以安全地被多个并发线程使用。 - 只是说
  • 多线程可以安全地使用获得的FileLock对象,但是这个锁不适合控制多线程对文件的访问。也就是说 - 对象(FileLock)本身是线程安全的。不过,它不应该像你描述的那样使用。
【解决方案3】:

您打算将数据写入一个文件。因此,如果您尝试锁定整个文件,最好使用单个线程来完成这项工作。虽然你生成了 20 个线程,但是每次调用方法时只有一个在运行,其他的只是等待锁。

我建议您使用RandomAccessFile 将数据写入您的文件。然后每个线程可以在不锁定整个文件的情况下将一些唯一的数据写入文件。

部分演示代码如下

try {
    final RandomAccessFile file = new RandomAccessFile("/path/to/your/result.txt", "rw");
    final int numberOfThread = 20;
    final int bufferSize = 512;
    ExecutorService pool = Executors.newFixedThreadPool(numberOfThread);
    final AtomicInteger byteCounter = new AtomicInteger(0);
    final byte[] yourText = "Your data".getBytes();
    for (int i = 0; i < yourText.length; i++) {
        pool.submit(new Runnable() {
            @Override
            public void run() {
                int start = byteCounter.getAndAdd(bufferSize);
                int chunkSize = bufferSize;
                if (start + bufferSize > yourText.length) {
                    chunkSize = yourText.length - start;
                }
                byte[] chunkData = new byte[chunkSize];
                System.arraycopy(yourText, start, chunkData, 0, chunkSize);
                try {
                    file.write(chunkData);
                } catch (IOException e) {
                    //exception handle
                }
            }
        });
    }
    file.close();
} catch (Exception e) {
    //clean up
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-05
    • 1970-01-01
    • 2015-08-17
    • 2021-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多