我有一个关于多个线程使用相同变量时的竞争条件的问题。
例如:
private static final ContentHandler ORG_OMG_xmi = new RootXMLContentHandlerImpl(
"org.omg.xmi", new String[] { "xmi" }, "xmi",
"http://schema.omg.org/spec/XMI/2.1", null);
如何将ContentHandler更改为本地线程,以便可以同时与多个线程一起使用?
答案 0 :(得分:1)
如评论中所述:只要已知该字段的内容是线程安全的,就不必使多个线程访问的每个静态字段都成为本地线程。很好的例子是典型的不可变类,例如String
,Integer
,...
也就是说,您可以使用Java8及更高版本将ContentHandler
包裹在ThreadLocal
中:
private static final ThreadLocal<ContentHandler> ORG_OMG_xmi = ThreadLocal.withInitial(
() -> new RootXMLContentHandlerImpl("org.omg.xmi", new String[] { "xmi" },
"xmi", "http://schema.omg.org/spec/XMI/2.1", null));
在Java8之前,您可以使用以下方法实现相同的目标:
private static ThreadLocal<ContentHandler> ORG_OMG_xmi =
new ThreadLocal<ContentHandler>() {
@Override public ContentHandler initialValue() {
return new RootXMLContentHandlerImpl("org.omg.xmi", new String[] { "xmi" },
"xmi", "http://schema.omg.org/spec/XMI/2.1", null));
}
};
有了ThreadLocal
,每个线程都会得到它自己的RootXMLContentHandlerImpl
实例,可以通过在get()
上调用ThreadLocal
来访问它:
ContentHandler myVeryThreadLocalContentHandler = ORG_OMG_xmi.get();
答案 1 :(得分:0)
如果您希望ContentHandler
是线程本地的,则可以使用run
方法(或run
调用的方法)对其进行声明和初始化,例如:
public void run() {
final ContentHandler ORG_OMG_xmi = new RootXMLContentHandlerImpl("org.omg.xmi", new String[] { "xmi" }, "xmi", "http://schema.omg.org/spec/XMI/2.1", null);
}
这样,就不会在线程之间共享它。