2012-02-02 22 views
7

Có phải javax.xml.XPathFactory.newInstance() là luồng an toàn không?Java XPathFactory thread-safety

Tôi hỏi vì tôi thấy tài liệu mơ hồ về nó. The JDK 5 docs không đề cập đến thread-safety ở tất cả; trong JDK 6 họ đã viết như sau:

Lớp XPathFactory không an toàn chỉ. Nói cách khác, đó là trách nhiệm của ứng dụng để đảm bảo rằng tối đa một luồng là bằng cách sử dụng đối tượng XPathFactory tại bất kỳ thời điểm cụ thể nào. Việc triển khai được khuyến khích đánh dấu các phương thức là được đồng bộ hóa để tự bảo vệ mình khỏi các khách hàng bị hỏng .

Theo tôi được biết, nó không phải là an toàn để có một thực hiện singleton cho XPathFactory, nhưng làm một cái gì đó như thế này nên được an toàn:

XPath xPathEvaluator = XPathFactory.newInstance().newXPath(); 

Tôi có thiếu cái gì? Liệu nó có phụ thuộc vào lớp thực tế mở rộng nó? Tôi có cần synchronize phương pháp có chứa câu lệnh trên không?

Trả lời

11

XPath xPathEvaluator = XPathFactory.newInstance(). NewXPath();

Điều đó là an toàn, vì mỗi luồng đều có nhà máy riêng (nhờ newInstance()). Không cần phải đồng bộ hóa ở đây.

Những gì bạn không thể làm một cách an toàn là nhận nhà máy một lần, sau đó chia sẻ giữa các chủ đề mà không cần đồng bộ hóa, ví dụ như một singleton. Điều tương tự cũng xảy ra đối với cá thể XPath (xPathEvaluator).

+0

Cảm ơn, tôi đã suy nghĩ tương tự, nhưng tôi muốn đảm bảo lại :). –

+1

Luôn ở đây để nắm tay :-) – Thilo

+5

Có nhiều điều xấu về thiết kế JAXP-XPath. Một trong số đó là XPathFactory.newInstance() rất tốn kém; khác là bạn được dự kiến ​​sẽ gọi nó liên tục trong mỗi chủ đề. Một cách khác là bạn không có cách nào để biết liệu bạn có lấy lại một công cụ XPath 1.0 hay một công cụ XPath 2.0 hay không. Hãy tự hỏi liệu bạn có thực sự muốn sử dụng cơ chế này không: nếu bạn biết công cụ XPath nào bạn muốn, có những cách tốt hơn để tải nó. –

3

"Một trong số đó là XPathFactory.newInstance() rất tốn kém;"

Tuyên bố đúng! Tôi nhận thấy rằng đối với mỗi chủ đề kêu gọi newInstance(), jaxp.properties phải nằm trên classpath và đọc bằng:

java.lang.Thread.State: BLOCKED (on object monitor) 
     at java.util.zip.ZipFile.getEntry(ZipFile.java:160) 
     - locked <0x0000000968dec028> (a sun.net.www.protocol.jar.URLJarFile) 
     at java.util.jar.JarFile.getEntry(JarFile.java:208) 
     at sun.net.www.protocol.jar.URLJarFile.getEntry(URLJarFile.java:107) 
     at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:114) 
     at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:132) 
     at java.net.URL.openStream(URL.java:1010) 
     at javax.xml.xpath.SecuritySupport$4.run(Unknown Source) 
     at java.security.AccessController.doPrivileged(Native Method) 
     at javax.xml.xpath.SecuritySupport.getURLInputStream(Unknown Source) 
     at javax.xml.xpath.XPathFactoryFinder._newFactory(Unknown Source) 
     at javax.xml.xpath.XPathFactoryFinder.newFactory(Unknown Source) 
     at javax.xml.xpath.XPathFactory.newInstance(Unknown Source) 
     at javax.xml.xpath.XPathFactory.newInstance(Unknown Source) 

ZipFile thực hiện cuộc gọi có nguồn gốc (để zlib Tôi tin) và giải nén jar, mà cần đĩa IO và giải nén nén zip. Trong trường hợp này, chúng tôi đã có hơn 1400 chủ đề chờ đợi trên khóa đó.