用Java编写多线程单文件

Mik*_*ike 5 java oop multithreading

这个问题似乎很常见,但是当多线程写入同一个文件(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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Two*_*The 6

您不需要同步纯读取,因此public static synchronized XLWriter getInstance()可以synchronized没有任何错误.您只需要同步写入,其中多个线程可能同时写入/读取相同的数据.

有两件事可以解决你的问题.最简单的方法是创建一个特殊的写入功能,然后是唯一要同步的功能:

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

在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;
  }
}
Run Code Online (Sandbox Code Playgroud)

一旦完成,只需确保在某个地方有一个解决方案来关闭hashmap中的所有文件.

有关进一步的想法:您还可以创建一个写入线程,其唯一目的是将内容写入该文件.如果此线程具有ConcurrentBlockingQueue,则其他线程可以将其部分添加到此队列而不是文件中,然后继续执行它们正在执行的任何操作,而写入线程是唯一有权访问该文件的线程.因此,不会出现写入问题,并且ConcurrentBlockingQueue中的线程安全性完全处理.