- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
这个问题似乎很常见,但我在多线程写入同一文件 (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 个线程尝试写入同一个文件。许多线程无法写入它并进入 Exception block 内......执行此操作的更好方法是什么?任何代码示例都会对我有很大帮助,因为我完成这个的时间非常少。谢谢。
最佳答案
您不需要同步纯读取,因此 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;
}
}
只需确保您在某处有一个解决方案,可以在完成后关闭 HashMap 中的所有文件。
进一步的想法:您也可以创建一个单一的写入线程,其唯一目的是将内容写入该文件。如果这个线程有一个 ConcurrentBlockingQueue ,其他线程可以将他们的部分而不是文件添加到这个队列中,然后继续他们正在做的任何事情,而写线程是唯一一个有权访问文件的线程。因此不会出现写入问题,并且线程安全完全在 ConcurrentBlockingQueue 中处理。
关于java - Java多线程单文件编写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19907582/
我是一名优秀的程序员,十分优秀!