Java——ThreadLocal类

一,引入ThreadLocal

/*测试ThreadLocal对象
 * 	 ThreadLocal:这个类提供了一个线程本地的变量。
 * 			这些变量在被共享访问的情况下在不同的线程里是独立的 ( 必须通过 get 和 set 方法来访问 ) 。
 *  很显然该类提供了一个机制可以防止多线程访问带来的不安全机制。实际上就是在线程本地保存一个变量,
 *  而不是通过共享变量。这个就要看我们的使用场合了,如果我们确实需要共享的数据,那还是必须通过同步机制来保证数据的安全。
 *  如果有些情况希望不同的线程保存的变量各自分开,那用这个还是比较合适的。

 ThreadLocal 这个类本身不是代表线程要访问的变量,这个类的成员变量才是。
 JDK1.5 给 ThreadLocal 加了泛型功能,即是 ThreadLocal<T>, 这个泛型 T 即是要线程的本地变量。
 线程通过 ThreadLocal 的 get 和 set 方法去访问这个变量 T 。 ThreadLocal 提供了一个机制,
 它能保证线程通过这个来访问它来访问类型为 T 的变量的时候是不同的拷贝。所以访问该变量必须通过 Threadlocal
 这个类只提供了两个 public 方法,即是 get() 和 set ()方法来访问。

 同时还提供了一个 inintValue() 的 protected 方法。该方法用来初始化变量值。

 注意 :默认情况下 initValue(), 返回 null 。线程在没有调用 set 之前,第一次调用 get 的时候,
 get 方法会默认去调用 initValue 这个方法。所以如果没有覆写这个方法,可能导致 get 返回的是 null 。
 当然如果调用过 set 就不会有这种情况了。但是往往在多线程情况下我们不能保证每个线程的在调用 get 之前都调用了 set ,
 所以最好对 initValue 进行覆写,以免导致空指针异常。 

 * */

       测试,在没有ThreadLocal的时候:

public class TestThreadLocal {
	public static int a = 0;

	public static void main(String[] args) {
		MyThread myThread=new MyThread();
		myThread.start();
		for(int i=0;i<5;i++){

			System.out.println(Thread.currentThread().getName()+":"+a);

		}
	}

	public static class MyThread extends Thread {
		public void run(){
			for(int i=0;i<5;i++){
				a=++a;

				System.out.println(Thread.currentThread().getName()+":"+a);

			}
		}
	}

}

  测试结果:

main:1
main:2
main:3
main:4
main:5
Thread-0:6
Thread-0:7
Thread-0:8
Thread-0:9
Thread-0:10

   发现结果很混乱,两个线程的执行明显有交叉。

   使用ThreadLocal之后:

public class TestThreadLocal {
	//public static int a = 0;
	public static ThreadLocal<Integer> a=new ThreadLocal<Integer>(){
		public Integer initialValue(){//初始化a的值
			return 0;
		}
	};

	public static void main(String[] args) {
		MyThread myThread=new MyThread();
		myThread.start();
		for(int i=0;i<5;i++){
			//a=++a;
			a.set(a.get()+1);
			System.out.println(Thread.currentThread().getName()+":"+a.get());

		}
	}

	public static class MyThread extends Thread {
		public void run(){
			for(int i=0;i<5;i++){
				//a=++a;
				a.set(a.get()+1);
				System.out.println(Thread.currentThread().getName()+":"+a.get());

			}
		}
	}

}

结果:

Thread-0:1
Thread-0:2
Thread-0:3
Thread-0:4
Thread-0:5
main:1
main:2
main:3
main:4
main:5

  使用了线程本地变量之后,我们必须通过get和set方法对变量进行读写。

二,简单介绍ThreadLocal

     

           

 /**
     * Returns the current thread's "initial value" for this
     * thread-local variable.  This method will be invoked the first
     * time a thread accesses the variable with the {@link #get}
     * method, unless the thread previously invoked the {@link #set}
     * method, in which case the <tt>initialValue</tt> method will not
     * be invoked for the thread.  Normally, this method is invoked at
     * most once per thread, but it may be invoked again in case of
     * subsequent invocations of {@link #remove} followed by {@link #get}.
     *
     * <p>This implementation simply returns <tt>null</tt>; if the
     * programmer desires thread-local variables to have an initial
     * value other than <tt>null</tt>, <tt>ThreadLocal</tt> must be
     * subclassed, and this method overridden.  Typically, an
     * anonymous inner class will be used.
     *
     * @return the initial value for this thread-local
     */
    protected T initialValue() {
        return null;
    }

    

        变量的初始化操作在这里完成,默认返回null,建议override此方法,确保get之前已进行过set操作,防止get的时候出错。

   

 public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }

      在ThreadLocal类中,有一个内部静态 类ThreadLocalMap,在这里存放着以key为当前threadLocal的object。


 public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

     set方法也是这样类似的,ThreadLocal里面通常放入的值通常就是采用这两种方法进行操作的,哦,还有remove:

 

 public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }

   好多代码のの。。。。大致先瞅瞅,然后接着切换回我们的spring源码解析,这篇只是小 插曲。

时间: 2024-08-31 00:46:05

Java——ThreadLocal类的相关文章

实例讲解Java并发编程之ThreadLocal类_java

ThreadLocal类可以理解为ThreadLocalVariable(线程局部变量),提供了get与set等访问接口或方法,这些方法为每个使用该变量的线程都存有一份独立的副本,因此get总是返回当前执行线程在调用set时设置的最新值.可以将ThreadLocal<T>视为 包含了Map<Thread,T>对象,保存了特定于该线程的值. 概括起来说,对于多线程资源共享的问题,同步机制采用了"以时间换空间"的方式,而ThreadLocal采用了"以空间

简单分析Java线程编程中ThreadLocal类的使用_java

一.概述  ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是threadlocalvariable(线程局部变量).也许把它命名为ThreadLocalVar更加合适.线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突.   从线程的角度看,每个线程都保持一个对其

Java 中ThreadLocal类详解_java

ThreadLocal类,代表一个线程局部变量,通过把数据放在ThreadLocal中,可以让每个线程创建一个该变量的副本.也可以看成是线程同步的另一种方式吧,通过为每个线程创建一个变量的线程本地副本,从而避免并发线程同时读写同一个变量资源时的冲突. 示例如下: import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import ja

Java ThreadLocal 使用详解

引言 ThreadLocal的官方API解释为: "该类提供了线程局部 (thread-local) 变量.这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副 本.ThreadLocal 实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联." 大概的意思有两点: ThreadLocal提供了一种访问某个变量的特殊方式:访问到的变量属

[Java] ThreadLocal的使用规则和源码分析

版权声明:请尊重个人劳动成果,转载注明出处,谢谢!http://blog.csdn.net/amazing7/article/details/51313851 目录(?)[+] ThreadLocal是什么? 线程局部变量,访问某个变量的每个线程都有自己的局部变量,它独立于变量的初始化副本.     它的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突.从线程的角度看,就好像每一个线程都完全拥有该变量.    

Java ThreadLocal的使用

原文链接  作者: Jakob Jenkov 译者: 林威建[weakielin@gmail.com] Java中的ThreadLocal类允许我们创建只能被同一个线程读写的变量.因此,如果一段代码含有一个ThreadLocal变量的引用,即使两个线程同时执行这段代码,它们也无法访问到对方的ThreadLocal变量. 如何创建ThreadLocal变量 以下代码展示了如何创建一个ThreadLocal变量: private ThreadLocal myThreadLocal = new Thr

关于Java ThreadLocal的疑问

问题描述 ThreadLocal作为一个可以将数据进行线程隔离的解决方法,其本质还是将数据存放在各个线程对象中(数据存放在Thread的ThreadLocalMap threadLocals中):那么为什么JDK不在设计的时候就使Thread对象具有保存线程上下文的能力呢?比如可以这样:public class Thread{...private Map<Object,Object> contexts = new WeakHashMap<Object,Object>();publi

java中有类的子类一说,那有对象的子对象一说吗?

问题描述 java中有类的子类一说,那有对象的子对象一说吗? java中有类的子类一说,那有对象的子对象一说吗?新手提问莫见笑. 解决方案 类的子类专业点说叫继承,对象的子对象你可以理解成方法的重写或重载等. 解决方案二: 那是不是类中有内部类就可以呢?

漫谈Java实例化类

  Java 中实例化类的动作,你是否还是一成不变 new 对应对象呢?     经手的项目多了,代码编写量自然会增加,渐渐的会对设计模式产生感觉.     怎样使书写出来的类实例化动作,高内聚,低耦合,又兼具一定的扩展能力呢?     本文试图从几段鲜活的代码入手,给大家呈现不一样的 Java 实例化类.     下面代码取自 com.google.zxing 源码实现: public BitMatrix encode(String contents, BarcodeFormat format