2013-06-06 14 views
-2

線程和ThreadLocal的聯合,我有一個聲明如下一些方法:如何用Java

這個類被聲明爲使用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(); 

此線程正常工作,但在第(2)行發生NullPointerException。 正如我調查該方法獲得返回null在行(1)。

這真的讓我很困惑。我不明白爲什麼會出現這個問題。請給我一些澄清,謝謝。

+2

我想回答你的問題,但我發現它太混亂。你的例子中有多個編譯錯誤,而且看起來不完整。由於'search'調用'getCurrent',執行的順序看起來與你描述的不同。 –

回答

0

我做了一些測試,問題是因爲私人靜態ThreadLocal變量,我不知道爲什麼,但這不是鏈接對象到ThreadLocal,似乎該對象沒有被創建。我需要更多的時間來進行調查。

反正我看到了兩個解決方案,爲您解決這個問題:

  1. 創建這個類作爲一個Singleton

    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();

4

您正在初始化ConversationUser.currentnew ThreadLocal<ConversationUser>(),但不進行匿名擴展以覆蓋initialValue(),就像您爲ThreadContext.threadLocal一樣。正因爲如此,當第一次調用get時,沒有什麼可以告訴它如何填充自己。由於沒有代碼調用set手動填充它,因此get返回null

有關更多信息和示例,請參閱ThreadLocal javadocs。

+0

我想我會剛剛取消刪除,因爲人們在重複我。 –

+0

+1剛剛看到你的帖子,當我發佈我的帖子時沒有看到它 – fmodos

+0

@fmodos是的,當我懷疑這個問題時,短暫刪除它是錯誤的。但即使問題不完全清楚,它似乎也是有用的信息。對困惑感到抱歉。 –