下面的例子中创建了两个线程,每个线程中存在多个局部变量。要使对象 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 是多个线程共享使用的,那还不乱套了。
就爱阅读 www.92to.com 网友整理上传, 为您提供最全的知识大全, 期待您的分享,转载请注明出处。
来源: