我想创建一个线程安全的SAX解析器的单例实例。
但我无法使用随需应变的习惯用法,因为SAX解析器会抛出SAXException,如果它是一个类变量则无法处理。这是我写的代码。
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;
}
}
有没有更好的方法来实现它?
答案 0 :(得分:1)
但我无法使用随需应变的习惯用法,因为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();
}
}