It is difficult for me to solve the following two implementations. I want to cache the javax.xml.parsers.DocumentBuilder object for each thread. My main concern is runtime performance - Hench. I would be happy to avoid as much GC as possible. Memory is not a problem.
I have written two POC implementations and will be glad to hear from the PROS / CONS community regarding each of them.
Thanks for helping the guys.
Option No. 1 - WeakHashMap
import java.io.IOException;
import java.io.StringReader;
import java.util.WeakHashMap;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class DocumentBuilder_WeakHashMap {
private static final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
private static final WeakHashMap<Thread, DocumentBuilder> CACHE = new WeakHashMap<Thread, DocumentBuilder>();
public static Document documentFromXMLString(String xml) throws SAXException, IOException, ParserConfigurationException {
DocumentBuilder builder = CACHE.get(Thread.currentThread());
if(builder == null) {
builder = factory.newDocumentBuilder();
CACHE.put(Thread.currentThread(), builder);
}
return builder.parse(new InputSource(new StringReader(xml)));
}
}
Option number 2 - ThreadLocal
import java.io.IOException;
import java.io.StringReader;
import java.lang.ref.WeakReference;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class DocumentBuilder_ThreadLocal {
private static final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
private static final ThreadLocal<WeakReference<DocumentBuilder>> CACHE =
new ThreadLocal<WeakReference<DocumentBuilder>>() {
@Override
protected WeakReference<DocumentBuilder> initialValue() {
try {
return new WeakReference<DocumentBuilder>(factory.newDocumentBuilder());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
public static Document documentFromXMLString(String xml) throws ParserConfigurationException, SAXException, IOException {
WeakReference<DocumentBuilder> builderWeakReference = CACHE.get();
DocumentBuilder builder = builderWeakReference.get();
if(builder == null) {
builder = factory.newDocumentBuilder();
CACHE.set(new WeakReference<DocumentBuilder>(builder));
}
return builder.parse(new InputSource(new StringReader(xml)));
}
}
They both do the same (expose documentFromXMLString () to the outside world), and which one would you use?
Thank you, Maxim.