首页 > 程序开发 > 综合编程 > 其他综合 >

ThreadLocal实例(2)

2017-02-13

ThreadLocal实例(2):下面的例子中创建了两个线程,每个线程中存在多个局部变量。要使对象A和对象B输出当前线程的局部变量,需要使用ThreadLocal,多个变量放到一个实体类中实现。

ThreadLocal实例(2):下面的例子中创建了两个线程,每个线程中存在多个局部变量。要使对象A和对象B输出当前线程的局部变量,需要使用ThreadLocal,多个变量放到一个实体类中实现。
import java.util.Random;

import cn.threadLocal.ThreadLocalTest.A;
import cn.threadLocal.ThreadLocalTest.B;

public class ThreadLocalBean {

    /**
     * 将线程中的多个变量放到实体中
     */
    public static void main(String[] args) {

        for(int i=0;i<2;i++){
            new Thread(new Runnable(){
                @Override
                public void run() {
               int  data=new Random().nextInt();
               // 获取当前线程的student的对象,该对象已存入ThreadLocal中,变量互不打扰
               student st=student.getInstance();
               st.setAge(data);
             System.out.println(Thread.currentThread().getName()+"has put data :"+data);
                new A().get();
                new B().get();
                }

            }).start();
            }
        }

        static class A{
            public void get(){
             student st=student.getInstance(); 
            System.out.println("A "+Thread.currentThread().getName()+"has put data :"+st.getAge());
            }
        }

        static class B{
            public void get(){
                 student st=student.getInstance(); 
                System.out.println("b "+Thread.currentThread().getName()+"has put data :"+st.getAge());
                }
        }
    }



class student{

    public static student getInstance(){
        // 通过ThreadLocal的get()和set()函数得到的对象是改线程自己使用的对象,其他线程获取不到。每个线程使用不同的对象。
        /**
         * 本例中创建了两个线程,每个线程都有自己对应的student对象,不是同一个对象。
         * 通过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,
         * 执行ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,
         * ThreadLocal实例是作为map的key来使用的。
         */
        student instance=(student) local.get();
        if(instance==null){
            instance=new student();
            local.set(instance);
        }
        return instance;
    }
    private static ThreadLocal local=new ThreadLocal();

    private int age;
    private String name ;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

}

二. 像ThreadLocal典型的应用莫过于Spring,Hibernate等框架中对于多线程的处理了.

下面来看一个hibernate中典型的ThreadLocal的应用

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;  
}  

可以看到在getSession()方法中,首先判断当前线程中有没有放进去session,如果还没有,那么通过sessionFactory().openSession()来创建一个session,再将session set到线程中,实际是放到当前线程的ThreadLocalMap这个map中,这时,对于这个session的唯一引用就是当前线程中的那个ThreadLocalMap(下面会讲到),而threadSession作为这个值的key,要取得这个session可以通过threadSession.get()来得到,里面执行的操作实际是先取得当前线程中的ThreadLocalMap,然后将threadSession作为key将对应的值取出。这个session相当于线程的私有变量,而不是public的。
显然,其他线程中是取不到这个session的,他们也只能取到自己的ThreadLocalMap中的东西。要是session是多个线程共享使用的,那还不乱套了。

相关文章
最新文章
热点推荐