English 中文(简体)
执行得更好: 以韦克哈什马普为基础或以当地人为基地的藏匿点为基础?
原标题:Which implementation is better: Cache based on WeakHashMap or cache based on ThreadLocal?

I m having hard time to decide between the following two implementations. I want to cache the javax.xml.parsers.DocumentBuilder object, per thread. My main concern is runtime performance - Hench I would be happy to avoid as much GC as possible. Memory is not an issue.

我写了两个POC执行书,并乐于听取社区项目/CONS关于每个项目的发言。

感谢这些帮助。

Option #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 #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)));
    }
}

两者都是一样的(将FromXMLString(FromXMLString)文件传给外部世界),以便你们能够使用?

Thank you, Maxim.

最佳回答

The ThreadLocal solution is better as long as you don t use the weakreference but rather use directly a ThreadLocal<DocumentBuilder>. Access to the ThreadLocal value is faster because the thread directly references an array containing all ThreadLocal values and it has just to compute the index in this array to do the lookup. Look at the ThreadLocal source to see why the index computation is fast (int index = hash & values.mask;)

问题回答

BEW!

<代码>Thread local将无限期地提及DocumentBuilder ,其中提及该校正版上的最新XML文件。

这可能被视为记忆泄露的后果:

  • If the JAXP implementation is loaded in a Web Application (say, Xerces or Oracle s xmlparser2.jar), this retained reference to the DocumentBuilder will cause all classes of your web application to leak upon undeploy, eventually leading to an OutOfMemoryError: PermGenSpace! (Google around for more info on this topic)
  • If the latest XML document parsed by a DocumentBuilder is large, it will keep taking up memory until a new XML document is parsed on that thread. If you have long-running threads in a thread pool (such as in a J2EE container), this might be an issue, especially if a lot of large documents need to be parsed. Yes, eventually the memory will be released, but you might run out of usable memory before that happens and the GC will not be able to clean up the XML document while a reference to the DocumentBuilder exists.

如果与你有关,则决定......

The WeakHashMap alone will fail, because it is not thread safe:
"Like most collection classes, this class is not synchronized."
(3rd paragraph at the JavaDoc)

由于同步化需要时间和<代码>。 收集信息 won跃,你应坚持<代码>。 校对地方





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签