Using threadlocal to manage sqlsession objects in MyBatis

Source: Internet
Author: User



Transfer from http://blog.csdn.net/qq_29227939/article/details/52029065


 
public class MybatisUtil {

    private static SqlSessionFactory factory;
    // Solve the contention problem.
    private static ThreadLocal <SqlSession> localSessions = new ThreadLocal <SqlSession> ();

    static {
        Reader reader = null;
        try {
            // Load Mybatis configuration file
            reader = Resources.getResourceAsReader ("mybatis.xml");
            // Create a SqlSessionFactory object.
            factory = new SqlSessionFactoryBuilder (). build (reader);
        } catch (IOException e) {
            e.printStackTrace ();
        } finally {
            if (reader! = null) {
                try {
                    reader.close ();
                } catch (IOException e) {
                    e.printStackTrace ();
                }
            }
        }
    }

    // Get Session object
    public static SqlSession getSession () {
        SqlSession session = localSessions.get ();
        if (session == null) {
            session = factory.openSession ();
            localSessions.set (session);
        }
        return session;
    }

    // method to close session
    public static void closeSession () {
        SqlSession session = localSessions.get ();
        if (session! = null) {
            session.close ();
            localSessions.remove ();
        }
    }
}


First, ThreadLocal is not used to solve multi-threaded access problems with shared objects, and in general, objects in the thread through Threadlocal.set () are objects that the thread itself uses, and other threads do not need access or access. Different objects are accessed in each thread.

In addition, it is said that threadlocal allows each thread to maintain its own independent object, not by Threadlocal.set (), but by creating an object through the operation of the new object in each thread, creating a copy or copy of each thread that is not an object. The reference to this newly created object is saved to a map of each thread by Threadlocal.set (), each thread has a map that executes Threadlocal.get (), and each thread pulls the object from its own map and So the objects in their own thread are taken out, and the threadlocal instance is used as the key to the map.

If Threadlocal.set () goes in the same object that multiple threads share, then the Threadlocal.get () of multiple threads gets the shared object itself, or there is a concurrent access problem.

Here's a typical threadlocal application in hibernate:


 private static final ThreadLocal threadSession = new ThreadLocal();  
      
    public static Session getSession() throws InfrastructureException {  
        Session s = (Session) threadSession.get();  
        try {  
            if (s == null) {  
                s = getSessionFactory().openSession();  
                threadSession.set(s);  
            }  
        } catch (HibernateException ex) {  
            throw new InfrastructureException(ex);  
        }  
        return s;  
    }  




As you can see in the GetSession () method, first determine if there is a session in the current thread, and if not, then use Sessionfactory (). Opensession () to create a session and then the session Set into a thread, it is actually placed in the current thread's threadlocalmap this map, when the only reference to the session is the current thread of the Threadlocalmap (as described below), And threadsession as the key of this value, to get this session can be obtained by Threadsession.get (), the operation is actually to get the threadlocalmap in the current thread, The threadsession is then removed as a key by the corresponding value. This session is equivalent to the private variable of the thread, not public.
Obviously, other threads are not able to get this session, and they can only take things from their own threadlocalmap. If the session is shared with multiple threads, it's not a mess.
Imagine how to achieve it without threadlocal? It may be troublesome to create a session in action and then upload the session to the service and DAO. Or you can define a static map, the current thread as a key, the creation of the session as a value, put into the map, it should be OK, this is the general idea, but in fact, the implementation of Threadlocal is the opposite, it is in each thread has a map, And the threadlocal instance as key, so that the number of items in each map is very small, and when the thread is destroyed when the corresponding things are also destroyed, do not know what other advantages besides these.
In short, threadlocal is not used to solve the problem of object sharing access, but mainly provides the method of preserving objects and the convenient way of object access to avoid parameter passing. Summed up two points:
1. Each thread has its own Threadlocalmap class object that can hold its own object to it, and the threads can access their own objects correctly.


2. A common threadlocal static instance is stored as a key, a reference to a different object is saved to the threadlocalmap of a different thread, and then the thread executes all the way through the Get () method of the static threadlocal instance to get the object that it has saved. Avoids the hassle of passing this object as a parameter.



Of course, if you want to put the thread shared by Threadlocal.set () to the thread can also be implemented to avoid parameter passing access, but note that get () to the same shared object, concurrent access problems to be solved by other means. But generally, thread-shared objects can be accessed conveniently by setting a static variable of a class, and it doesn't seem necessary to put it in a thread.

For threadlocal applications, I think the best thing to do is to access the objects by multiple instances of threads (one instance per thread), and this object is used in many places.
Let's look at the implementation principle of threadlocal (jdk1.5 source)


public class ThreadLocal<T> {  
        /** 
         * ThreadLocals rely on per-thread hash maps attached to each thread 
         * (Thread.threadLocals and inheritableThreadLocals).  The ThreadLocal 
         * objects act as keys, searched via threadLocalHashCode.  This is a 
         * custom hash code (useful only within ThreadLocalMaps) that eliminates 
         * collisions in the common case where consecutively constructed 
         * ThreadLocals are used by the same threads, while remaining well-behaved 
         * in less common cases. 
         */  
        private final int threadLocalHashCode = nextHashCode();  
      
        /** 
         * The next hash code to be given out. Accessed only by like-named method. 
         */  
        private static int nextHashCode = 0;  
      
        /** 
         * The difference between successively generated hash codes - turns 
         * implicit sequential thread-local IDs into near-optimally spread 
         * multiplicative hash values for power-of-two-sized tables. 
         */  
        private static final int HASH_INCREMENT = 0x61c88647;  
      
        /** 
         * Compute the next hash code. The static synchronization used here 
         * should not be a performance bottleneck. When ThreadLocals are 
         * generated in different threads at a fast enough rate to regularly 
         * contend on this lock, memory contention is by far a more serious 
         * problem than lock contention. 
         */  
        private static synchronized int nextHashCode() {  
            int h = nextHashCode;  
            nextHashCode = h + HASH_INCREMENT;  
            return h;  
        }  
      
        /** 
         * Creates a thread local variable. 
         */  
        public ThreadLocal() {  
        }  
      
        /** 
         * Returns the value in the current thread‘s copy of this thread-local 
         * variable.  Creates and initializes the copy if this is the first time 
         * the thread has called this method. 
         * 
         * @return the current thread‘s value of this thread-local 
         */  
        public T get() {  
            Thread t = Thread.currentThread();  
            ThreadLocalMap map = getMap(t);  
            if (map != null)  
                return (T)map.get(this);  
      
            // Maps are constructed lazily.  if the map for this thread  
            // doesn‘t exist, create it, with this ThreadLocal and its  
            // initial value as its only entry.  
            T value = initialValue();  
            createMap(t, value);  
            return value;  
        }  
      
        /** 
         * Sets the current thread‘s copy of this thread-local variable 
         * to the specified value.  Many applications will have no need for 
         * this functionality, relying solely on the {@link #initialValue} 
         * method to set the values of thread-locals. 
         * 
         * @param value the value to be stored in the current threads‘ copy of 
         *        this thread-local. 
         */  
        public void set(T value) {  
            Thread t = Thread.currentThread();  
            ThreadLocalMap map = getMap(t);  
            if (map != null)  
                map.set(this, value);  
            else  
                createMap(t, value);  
        }  
      
        /** 
         * Get the map associated with a ThreadLocal. Overridden in 
         * InheritableThreadLocal. 
         * 
         * @param  t the current thread 
         * @return the map 
         */  
        ThreadLocalMap getMap(Thread t) {  
            return t.threadLocals;  
        }  
      
        /** 
         * Create the map associated with a ThreadLocal. Overridden in 
         * InheritableThreadLocal. 
         * 
         * @param t the current thread 
         * @param firstValue value for the initial entry of the map 
         * @param map the map to store. 
         */  
        void createMap(Thread t, T firstValue) {  
            t.threadLocals = new ThreadLocalMap(this, firstValue);  
        }  
      
        .......  
      
        /** 
         * ThreadLocalMap is a customized hash map suitable only for 
         * maintaining thread local values. No operations are exported 
         * outside of the ThreadLocal class. The class is package private to 
         * allow declaration of fields in class Thread.  To help deal with 
         * very large and long-lived usages, the hash table entries use 
         * WeakReferences for keys. However, since reference queues are not 
         * used, stale entries are guaranteed to be removed only when 
         * the table starts running out of space. 
         */  
        static class ThreadLocalMap {  
      
        ........  
      
        }  
      
    }  


You can see that the variables in the Threadlocal class have only these 3 int types:


  private final int threadLocalHashCode = nextHashCode();  
    private static int nextHashCode = 0;  
    private static final int HASH_INCREMENT = 0x61c88647;  


And as a threadlocal instance of the variable only threadlocalhashcode this one, Nexthashcode and hash_increment is a static variable threadlocal class, in fact Hash_ Increment is a constant that represents the increment of the Threadlocalhashcode value of the two threadlocal instances that are continuously allocated, and the Nexthashcode That represents the value of the Threadlocalhashcode of the next threadlocal instance that is about to be allocated.

Take a look at what you did when you created a ThreadLocal instance, new ThreadLocal (), and see from the constructor ThreadLocal () that there is nothing in it, the only operation is this sentence:





 
private final int threadLocalHashCode = nextHashCode(); 





So what does Nexthashcode () do:


 private static synchronized int nextHashCode() {  
        int h = nextHashCode;  
        nextHashCode = h + HASH_INCREMENT;  
        return h;  
    }  



is to assign the value of the next hashcode value of the Threadlocal class to the Threadlocalhashcode of the instance Nexthashcode, and then nexthashcode the value to hash_increment this value.

So the variable of Threadlocal instance is only this threadlocalhashcode, and it is final, to distinguish different threadlocal instances, the Threadlocal class is mainly used as a tool class. So where does the Threadlocal.set () go in?

Take a look at the set () method above and merge the two sentences into


Threadlocalmap map = Thread.CurrentThread (). Threadlocals;  


This Threadlocalmap class is an inner class defined in threadlocal, but its instance is used in the thread class:


 public class Thread implements Runnable {  
        ......  
      
        /* ThreadLocal values pertaining to this thread. This map is maintained 
         * by the ThreadLocal class. */  
        ThreadLocal.ThreadLocalMap threadLocals = null;    
        ......  
    }  


Look at this sentence again:


    if (map != null)  
        map.set(this, value);  
 





That is, the threadlocal instance as a key, the object to keep as a value, set to the current thread of the Threadlocalmap, Get () method also you see the code will understand. via:http://www.iteye.com/topic/103804









Using threadlocal to manage sqlsession objects in MyBatis


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.