-2

我有一些声明如下的方法:

此类声明用于从容器ThreadLocal中获取组件。Service

public class ThreadContext {
    private Connector connector;
    private static ThreadLocal threadLocal = new ThreadLocal() {        
        @Override
        protected Connector initialValue() {
            Service service =  
                   (Service) Container.getComponentInstanceOfType(Service.class);
            Connector connector = service.getConnector();  
            return connector;
        }
    };

    public static Connector get() {
        return Connector threadLocal.get();
    }
}

Connector中产阶级

public class Connector {
    public Collection<Result> search() {
        User user = ConversationUser.getCurrent()
    }
}

也被ConversationUser声明为使用ThreadLocal

public class ConversationUser {
    private static ThreadLocal<ConversationUser> current = 
                                            new ThreadLocal<ConversationUser>();

    public static ConversationUser getCurrent() {
        return current.get();//(1)
    }
}

然后,我写了一个线程来做如下的事情:

Thread thread = null;
thread = new Thread(new Runnable() {
    public void run(){
        ThreadContext context = new ThreadContext();          
        Collection<Result> result = context.get().search();//(2)
        resultsTemp.put("File", result);
    }
});          
thread.start();

该线程正常工作,但发生NullPointerException在第 (2) 行。正如我调查的那样,该方法在第 (1) 行返回 null。

我真的很困惑。我不明白为什么会出现问题。请给我一些澄清,谢谢。

4

2 回答 2

4

您正在初始化ConversationUser.currentnew ThreadLocal<ConversationUser>()而不是匿名扩展它来覆盖initialValue(),就像您为ThreadContext.threadLocal. 因此,没有什么可以告诉它在get第一次调用时如何填充自己。由于没有代码调用set手动填充它,因此get返回null.

有关更多信息和有用的示例,请参阅ThreadLocaljavadocs。

于 2013-06-06T03:22:19.083 回答
0

我做了一些测试,问题是因为私有静态ThreadLocal变量,我不知道为什么,但这没有将对象链接到ThreadLocal,似乎没有创建对象。我需要更多时间来调查它。

无论如何,我看到了两种解决方案来解决这个问题:

  1. 将此类创建为单例

    public class ConversationUser extends ThreadLocal<ConversationUser>{
        private static ThreadLocal<ConversationUser> current= null;
    
    @Override
        protected ConversationUser initialValue() {
            return new ConversationUser();
        }
    
        public static ConversationUser getCurrent() {
            if (current == null) {
                current = new ConversationUser();
            }
            return current.get();
        }
    
        }
    

    //用法ConversationUser.getCurrent()

  2. 忘记这个静态变量,总是通过创建ThreadLocal对象的新实例来访问它

    public class ConversationUser extends ThreadLocal<ConversationUser>{
    
    @Override
        protected ConversationUser initialValue() {
            return new ConversationUser();
        }
    
        }
    

    //用法new ConversationUser().get();

于 2013-06-06T03:41:58.433 回答