我有一个执行 xml 解析的函数。我想让函数线程安全,但也尽可能优化(减少阻塞)。
简而言之,代码如下:
public Document doXML(InputStream s)
{
//Some processing.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder parser = factory.newDocumentBuilder();
Document xmlDoc = parser.parse(is);
return xmlDoc;
}
但我不想在每次调用时都创建一个新的 DocumentBuilderFactory 或 DocumentBuilder。
我想重用工厂和解析器,但我不确定它们是线程安全的。那么最佳的方法是什么?
1) 在类字段中缓存一个DocumentBuilderFactory并同步factory.newDocumentBuilder();这样每个线程都有自己的 DocumentBuilder 实例
2) 缓存 DocumentBuilderFactory 和 DocumentBuilder 并同步 parser.parse(is); 每个线程
我认为 (2) 是最好的,但这样做安全吗?我还可以避免同步阻塞吗?我希望它尽可能快。
谢谢?
最佳答案
如果您正在重用线程(如在线程池中),您可以将 DocumentBuilderFactory 声明为本地线程。为每个线程创建一个新集合会产生开销,但正如我所说,如果您重新使用,则后续开销非常低。
final ThreadLocal<DocumentBuilderFactory> documentBuilderFactor = new ThreadLocal<DocumentBuilderFactory>(){
public DocumentBuilderFactory initialValue(){
return DocumentBuilderFactory.newInstance();
}
}
public Document doXML(InputStream s)
{
//Some processing.
DocumentBuilderFactory factory = documentBuilderFactor.get();
DocumentBuilder parser = factory.newDocumentBuilder();
Document xmlDoc = parser.parse(is);
return xmlDoc;
}
在这里,您将为每个线程只创建一个 DocumentBuilderFactory。
我不知道 DocumentBuilder 在解析时是否是线程安全的(它是不可变的吗?)。但是如果 DocumentBuilder 在解析时是线程安全的,您可以使用我所说的相同机制。
此决议将使整体吞吐量尽可能快。
注意:这未经测试或编译,只是让您了解我所指的内容。
关于dom api上的java多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4217273/