zoukankan      html  css  js  c++  java
  • java-ThreadLocal常见的几种实现方式和实例

    简单介绍一下ThreadLocal的原理
    1.ThreadLocal会为每一个线程维护一个和该线程绑定的实例变量的副本
    2.因为每一个线程都拥有自己独立的实例变量副本,而不会和其它线程的副本冲突

    ThreadLocal类接口很简单,只有4个方法,我们先来了解一下:

    void set(Object value)设置当前线程的线程局部变量的值。

    public Object get()该方法返回当前线程所对应的线程局部变量。

    public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。

    protected Object initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。


    • 法一. 在用户类中定义一个ThreadLocal实例属性(通常是静态实例)把ThreadLocal就当做一个map操作,该set就set(加入Thread.currentThread为key),该get就get(加入Thread.currentThread为key)
    例1: 下面是hibernate文档里提供的辅助类HibernateUtil
    ThreadLocal 模式管理hibernate Session
    每个线程都能获得一个session的副本

    public class HibernateUtil {

        public static final ThreadLocal session =new ThreadLocal();

        public static final SessionFactory sessionFactory;

       static {
          try {
            sessionFactory = new Configuration().configure().buildSessionFactory();
          } catch (Throwable ex) {
               throw new ExceptionInInitializerError(ex);
            
            }
        
         public static Session currentSession () throws HibernateException {
            Session s = session.get ();
            if(s == null) {
              s = sessionFactory.openSession ();
              session.set(s);
               }
             return s;
           }
           
        public static void closeSession() throws HibernateException {
               Session s = session.get ();
            if(s != null) {
                s.close();
            }
            session.set(null);
        }
    }
    例2: HibernateSessionFactory 中 getSession()的实现 .
    另一种和上面辅助类HibernateUtil类似的HibernateSessionFactory ,是MyEclipse自动生成的

    public class HibernateSessionFactory {

      public static final ThreadLocal threadLocal =new ThreadLocal();
     
      public static Session getSession() throws HibernateException ...{
            Session session = (Session) threadLocal.get();

            if (session == null || !session.isOpen()) ...{
                if (sessionFactory == null) ...{
                    rebuildSessionFactory();
                }
                session = (sessionFactory != null) ? sessionFactory.openSession()
                        : null;
                threadLocal.set(session);
            }

            return session;
         
    例3:struts2 中 请求的 Dispatcher对象
    struts2 中 Dispatcher对象是核心功能对象
    Dispatcher对象接受了参数FilterDispatcher过滤器的FilterConfig传来的ServletContext,这样才接管了基本Servlet的一切功能
    FilterDispatcher过滤器的doFilter()方法,调用了Dispatcher对象的serviceAction()方法,并把HttpServletRequest对象和HttpServletResponse对象传入, 这个serviceAction()方法,就是整个Strtus2的主引擎

    struts2对每个request请求分配一个线程,为每个线程安排一个ThreadLocal模式的Dispatcher对象

    public class Dispatcher {

     private static ThreadLocal instance = new ThreadLocal();

     //Store the dispatcher instance for this thread.
      public static void setInstance(Dispatcher instance) {
     
         Dispatcher.instance.set(instance);

         // Tie the ObjectFactory threadlocal instance to this Dispatcher instance
                  if (instance != null) {
             Container cont = instance.getContainer();
                      if (cont != null) {
                 ObjectFactory.setObjectFactory(cont.getInstance(ObjectFactory.class));
                       } else {
                 LOG.warn("This dispatcher instance doesn't have a container, so the object factory won't be set.");
                       }
                } else {
             ObjectFactory.setObjectFactory(null);
             }
     }

     //Provide the dispatcher instance for the current thread.
       public static Dispatcher getInstance() {
         return instance.get();
     }

    private ServletContext servletContext;
    private Map initParams;

     public  Dispatcher(ServletContext servletContext, Map initParams) {
         this.servletContext = servletContext;
         this.initParams = initParams;
     }
    例4:Struts2的请求的ActionContext对象
    Struts2的ActionContext对象,是为了弥补strtus2 action跳出标准servlet框架而造成的和WEB环境失去联系的缺陷
    struts2对每个request请求分配一个线程,为每个线程安排一个ThreadLocal模式的ActionContext对象

     public class ActionContext implements Serializable {

         static ThreadLocal actionContext = new ThreadLocal();
        
         //Sets the action context for the current thread.
         public static void setContext(ActionContext context) {
             actionContext.set(context);
         }
         //Returns the ActionContext specific to the current thread.
         public static ActionContext getContext() {
             return (ActionContext) actionContext.get();
         }


    • 法二.用户类继承标准ThreadLocal类,覆写initialValue(),增加初始化实例语句
    public class ThreadLocal
    {
     private Map values = Collections.synchronizedMap(new HashMap());
                                  
     public Object get()
     {
      Thread curThread = Thread.currentThread();
      Object o = values.get(curThread);

      if (o == null && !values.containsKey(curThread))
      {
       o = initialValue();
       values.put(curThread, o);
      }
      
            return o;
     }

     public void set(Object newValue)
     {
      values.put(Thread.currentThread(), newValue);
     }

     public Object initialValue()
     {
      return null;
     }
    }
     
    public class Test1 extends ThreadLocal{
        @Override
      public Object initialValue()
      {
          //return null;
       return 你要保存副本的实例变量;
      }

    //get(),set()都不必覆写,因为标准ThreadLocal下都是Object类型.
    }


    • 法三. 在类内建匿名类或内部类,实际是法一和法二的结合

    例1:设一个匿名类
    SerialNum类,为每一个类分配一个序号:
    public class SerialNum
    {
     // The next serial number to be assigned
     private static int nextSerialNum = 0;
       
     private static ThreadLocal serialNum = new ThreadLocal()  {
      protected synchronized Object initialValue()
      {
       return new Integer(nextSerialNum++);        
      }
     };

     public static int get()
     {
      return ((Integer) (serialNum.get())).intValue();
     }
    }

    SerialNum类的使用非常简单:
    int t1 = SerialNum.get(); 即可。
    例2:设一个内部类
    public class ConnectionDispenser {
           
            private static class ThreadLocalConnection extends ThreadLocal {
               public Object initialValue() {
                      return DriverManager.getConnection(ConfigurationSingleton.getDbUrl());
               }
       }
      
        private ThreadLocalConnection conn = new ThreadLocalConnection();
       
        public static Connection getConnection() {
                return (Connection) conn.get();
       }
    }
  • 相关阅读:
    ERROR Function not available to this responsibility.Change responsibilities or contact your System Administrator.
    After Upgrade To Release 12.1.3 Users Receive "Function Not Available To This Responsibility" Error While Selecting Sub Menus Under Diagnostics (Doc ID 1200743.1)
    产品设计中先熟练使用铅笔 不要依赖Axure
    12.1.2: How to Modify and Enable The Configurable Home Page Delivered Via 12.1.2 (Doc ID 1061482.1)
    Reverting back to the R12.1.1 and R12.1.3 Homepage Layout
    常见Linux版本
    网口扫盲二:Mac与Phy组成原理的简单分析
    VMware 8安装苹果操作系统Mac OS X 10.7 Lion正式版
    VMware8安装MacOS 10.8
    回顾苹果操作系统Mac OS的发展历史
  • 原文地址:https://www.cnblogs.com/luckForever/p/7254131.html
Copyright © 2011-2022 走看看