Java 单例线程安全SAX解析器实例
我想创建一个SAX解析器的单例实例,它是线程安全的 但我不能使用随需应变的习惯用法,因为SAX解析器抛出SAXException,如果将其设为类变量,则无法处理该异常。这是我写的代码Java 单例线程安全SAX解析器实例,java,multithreading,singleton,sax,Java,Multithreading,Singleton,Sax,我想创建一个SAX解析器的单例实例,它是线程安全的 但我不能使用随需应变的习惯用法,因为SAX解析器抛出SAXException,如果将其设为类变量,则无法处理该异常。这是我写的代码 public class Parser { private static SAXParser parser; Parser() throws ParserConfigurationException, SAXException { if (parser==null) pars
public class Parser {
private static SAXParser parser;
Parser() throws ParserConfigurationException, SAXException {
if (parser==null)
parser=LazyHolder.factory.newSAXParser();
}
private static class LazyHolder {
private static final SAXParserFactory factory=SAXParserFactory.newInstance();
}
public SAXParser getInstance() {
return parser;
}
}
有没有更好的方法来实现这一目标
但我不能使用随需应变的习惯用法,因为SAX解析器抛出SAXException,如果将其设为类变量,则无法处理该异常
如果这只是为了在初始化期间绕过异常,则可以通过执行以下操作来绕过异常:
public class Wrapper {
private static MyClassThatThrows singleton;
static {
try {
singleton = new MyClassThatThrows();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
...
public static MyClassThatThrows getInstance() {
return singleton;
}
}
当然,如果解析器抛出,这将停止类的加载
但是,SAXParserFactory
和SAXParser
都不是线程安全的,因此您可以使用ThreadLocal
来为每个线程生成一个线程
public class Parser {
private final ThreadLocal<SAXParserFactory> factoryThreadLocal = new ThreadLocal<>() {
public SAXParserFactory initialValue() {
try {
return SAXParserFactory.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
public SAXParser getInstance() {
// you could catch and re-throw the RuntimeException if the caller should handle it
return factoryThreadLocal.get().newInstance();
}
}
公共类解析器{
私有最终ThreadLocal factoryThreadLocal=新ThreadLocal(){
公共SAXParserFactory初始值(){
试一试{
返回SAXParserFactory.newInstance();
}捕获(例外e){
抛出新的运行时异常(e);
}
}
};
公共SAXParser getInstance(){
//如果调用方应该处理RuntimeException,您可以捕获并重新抛出它
返回factoryThreadLocal.get().newInstance();
}
}
您认为SAXParser是安全的假设是错误的。请参阅下面的链接
之前我还认为SAXParser是线程安全的,有时我会出现以下错误,当一个线程已经在使用parser对象来解析xml,而另一个线程也试图使用相同的对象时,就会发生这种情况。当我为每个线程创建SAXParser实例时,异常得到了修复
org.xml.sax.SAXException:解析时不能调用FWK005 parse。
在com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1253)~[na:1.8.0\u 20]
在com.sun.org.apache.xerces.internal.jaxp.saxpasserimpl$jaxpsaxpasser.parse(saxpasserimpl.java:649)~[na:1.8.020]
在com.sun.org.apache.xerces.internal.jaxp.saxpasserimpl.parse(saxpasserimpl.java:333)~[na:1.8.020]
在javax.xml.parsers.SAXParser.parse(SAXParser.java:195)~[na:1.8.020]
我不明白这是怎么回事。是否希望几个线程使用相同的SAXParser实例?当一个线程在使用这个实例时,其他线程不能,对吗?不,我希望一个SAXParser实例可以被不同的线程同时使用。真的有可能吗?新的解析器实例有点昂贵。有没有有效的方法可以在多个线程中重用相同的实例。SAXParser不是线程安全的,这就是为什么不同的线程不能同时使用同一个实例。您可以通过几个线程重用一个实例,但不能同时逐个重用。如果您希望通过不同的线程进行并发解析,则必须创建SAXParser实例池。我们还可以为每个线程创建新实例。这也可以正常工作吗?