是javax.naming.InitialContext ThreadSafe

Deb*_*pam 10 java jndi thread-safety

目前我使用以下代码来查找正常POJO类的EJB3 sateless会话bean.(我们在JEE5中,所以我们不能在正常的POJO类中注入无状态会话Bean我必须使用查找)

import javax.naming.Context;  
import javax.naming.InitialContext;  
import javax.naming.NamingException;  

import org.apache.log4j.Logger;  

public Object getEJB(String jndiName) {  

                logger.debug("WEBSPHERE EJB Lookup : " + jndiName);  
                String modifiedJndiName = "";  
                Hashtable<Object, Object> properties = new Hashtable<Object, Object>();  
                properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");  
                properties.put(Context.PROVIDER_URL, "iiop://localhost:2809");  
                try {  
                    Context context = new InitialContext(properties);  
                    logger.debug("WEBSPHERE EJB Lookup Modified JNDI Name: " + modifiedJndiName);  
                    return context.lookup("ejblocal:"+modifiedJndiName);  
                }catch (NamingException ne) {  
                    logger.debug("Naming Exception occurred :"+jndiName +">>>"+ne.getMessage());  
                    logger.error(ne.getMessage(), ne);  
                }  

                return null;  
            }  
Run Code Online (Sandbox Code Playgroud)

那么Context对象是ThredSafe吗?我应该为每个调用创建Context对象[如此代码片段所示],还是我可以为所有线程重用Context?

Bal*_*usC 15

关于线程安全的答案通常已经在javadoc中提到,只要相关.事实上,InitialContextjavadoc提到了以下内容:

一个InitialContext实例与多个线程的并发访问不同步.每个操作不同InitialContext实例的多个线程不需要同步.需要同时访问单个InitialContext实例的线程应该在它们之间进行同步并提供必要的锁定.

最后一句证实了这一点:它不是线程安全的,每线程同步是必要的.但是,在您的特定代码示例中,不需要同步,因为它始终在方法本地范围中创建(即它绝对不在线程之间共享).如果InitialContext您的特定代码示例中的某个是实例变量,那么您必须将该synchronized关键字添加到该getEJB()方法中.

  • InitialContext不是线程安全的,我现在从经验中知道:).如果多个线程访问它,您必然会遇到运行时异常.我有类似OP(EJB在JBoss上运行)的情况,有两个线程在没有同步的情况下访问初始上下文并得到运行时异常:`java.lang.IllegalStateException:EJBCLIENT000025:没有EJB接收器可用于处理[... ]`.看完这个答案后,我同步访问,所有问题都消失了.大+1 :) (2认同)