【问题标题】:Multi threaded single file writing in Java用Java编写多线程单文件
【发布时间】:2013-11-11 13:28:05
【问题描述】:

这个问题似乎很常见,但是当多线程写入同一个文件(Excel)时,我遇到了问题。这是我的代码:

public class XLWriter {

private XLWriter() {
}

private static class SingletonHelper {
    private static final XLWriter INSTANCE = new XLWriter();
}

public static synchronized XLWriter getInstance() {
    return SingletonHelper.INSTANCE;
}

public static synchronized void writeOutput(Map<String, String> d) {
    try {
        --- Write file
    } catch (Exception e) {
        SOP("Not able to write output to the output file.");
    }
}

public static void createWorkBook(String fileName, String sheetName)
        throws IOException {
    try {
        -- Create workbook
    } catch (WriteException e) {
        System.out.println("Could not create workbook" + e);
    }
}

我正在使用 testng 框架,10 个线程尝试写入同一个文件。许多线程无法写入它并进入异常块......有什么更好的方法来做到这一点?任何代码示例都会对我有很大帮助,因为我完成这个的时间非常少。谢谢。

【问题讨论】:

  • 它是否适用于单线程? createWorkBook 方法不是 synchronized。这是故意的吗?这两种方法哪一种失败了?
  • 你得到什么样的异常?
  • 创建一个队列,每个线程将其数据写入其中。创建一个单独的写入器线程,它读取队列数据并保存到磁盘。
  • Threads and file writing的可能重复

标签: java multithreading oop


【解决方案1】:

您不需要同步纯读取,因此public static synchronized XLWriter getInstance() 可以在没有synchronized 的情况下运行而不会出现任何错误。您只需要同步写入,多个线程可能同时写入/读取相同的数据。

有两件事可以解决您的问题。最简单的方法是创建一个特殊的写入函数,然后它是唯一要同步的函数:

private void write(final File f, final Map<String, String> output) {
  synchronized(f) {
    // do the write
  }
}

在 f 上同步是正确的,因为这是必须以独占方式访问的共享资源。

只要告诉文件创建不要覆盖现有文件,就不需要更改 createWorkBook 函数,因为文件系统本身已经是线程安全的。现在您只需要一个已打开文件的查找表来获取适当的文件句柄,因为在任何时候打开的每个文件都必须只有一个文件。这可以使用像这样的 ConcurrentHashMap 来解决:

public void getFileFor(String filename) {
  File newFile = File(filename);
  File inList = fileHashMap.putIfAbsent(newFile);
  if (inList != null) {
    return inList;
  } else {
    return newFile;
  }
}

只要确保你在某处有一个解决方案,在你完成后关闭哈希图中的所有文件。

更多想法:您也可以创建一个写入线程,其唯一目的是将内容写入该文件。如果这个线程有一个ConcurrentBlockingQueue,其他线程可以将他们的部分添加到这个队列而不是文件中,然后继续他们正在做的任何事情,而写线程是唯一可以访问文件的人。因此不会出现写入问题,线程安全完全由 ConcurrentBlockingQueue 处理。

【讨论】:

  • 非常感谢您的详细回答。信息量很大。百万谢谢。
猜你喜欢
  • 2015-08-17
  • 1970-01-01
  • 1970-01-01
  • 2015-07-26
  • 2015-11-12
  • 2021-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多