Java中的ThreadLocal_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > Java中的ThreadLocal

Java中的ThreadLocal

 2013/9/28 18:49:17  tonlion2046  程序员俱乐部  我要评论(0)
  • 摘要:再了解ThreadLocal之前先看一个简单的Java线程示例。线程类:publicclassTestThread2extendsThread{inta;Stringb="a";@Overridepublicvoidrun(){for(inti=1;i<=3;i++){System.out.println(Thread.currentThread().getName()+""+a+""+b);a++;b=""+(char)(b.charAt(0)+1);}}}主测试类代码
  • 标签:thread Java

再了解ThreadLocal之前先看一个简单的Java线程示例。

线程类:

class="java" name="code">public class TestThread2 extends Thread {
	int a;
	String b = "a";

	@Override
	public void run() {
		for (int i = 1; i <= 3; i++) {
			System.out.println(Thread.currentThread().getName() + " " + a + " "
					+ b);
			a++;
			b = "" +(char)(b.charAt(0)+1);
		}
	}
}

主测试类代码:

public class MainTest {
	public static void main(String[] args) {
		Runnable test = new TestThread2();
		Thread a1 = new Thread(test,"线程1");
		Thread a2 = new Thread(test,"线程2");
		Thread a3 = new Thread(test,"线程3");
		//a1,a2,a3共享test对象的实例变量
		
		a1.start();
		a2.start();
		a3.start();
	}
}

?某个输出结果为:

线程1 10 a
线程1 11 b
线程1 12 c
线程2 13 d
线程3 14 e
线程2 14 e
线程2 15 f
线程3 17 g
线程3 18 h

??????? 由结果可以看到,test对象里的a,b变量被几个线程共享,所以他们的结果累加了。当然如果改变一种写法,几个线程不通过test对象创建,则不构成共享对象,那么几个都只用自己的成员变量,结果就会不一样了。代码:

public class MainTest {
	public static void main(String[] args) {
		//Runnable test = new TestThread2();
		Thread a1 = new Thread(new TestThread2(),"线程1");
		Thread a2 = new Thread(new TestThread2(),"线程2");
		Thread a3 = new Thread(new TestThread2(),"线程3");
		 
//		Thread a1 = new TestThread2();
//		Thread a2 = new TestThread2();
//		Thread a3 = new TestThread2();
		
		a1.start();
		a2.start();
		a3.start();
	}
}

?运行结果为:

线程1 0 a
线程3 0 a
线程1 1 b
线程1 2 c
线程3 1 b
线程3 2 c
线程2 0 a
线程2 1 b
线程2 2 c

??????? 好了,现在的问题就是能不能让共享的对象里的变量也有上面等效的结果,每个对象都把共享的对象属性处理成自己的局部变量。ThreadLocal就是用来达到这个目的的。更改线程类代码为:

public class TestThread2 extends Thread {

	private static ThreadLocal<Integer> a = new ThreadLocal<Integer>() {
		@Override
		protected Integer initialValue() {
			return 0;
		}
	};

	private static ThreadLocal<String> b = new ThreadLocal<String>() {
		@Override
		protected String initialValue() {
			return "a";
		}
	};

	@Override
	public void run() {
		for (int i = 1; i <= 3; i++) {
			System.out.println(Thread.currentThread().getName() + " " + a.get()
					+ " " + b.get());
			a.set(a.get() + 1);
			b.set("" + (char) (b.get().charAt(0) + 1));
		}
	}
}

?再次运行共享test对象的主程序测试类,打印结果如下:

线程1 0 a
线程2 0 a
线程2 1 b
线程2 2 c
线程3 0 a
线程3 1 b
线程3 2 c
线程1 1 b
线程1 2 c

?对于ThreadLocal的一般解释:

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

?ThreadLocal类位于java.lang下,即java.lang.ThreadLocal,对于这个类的解读和实现分析,网上已经有不少了:

http://sishuok.com/forum/blogPost/list/340.html

http://blog.csdn.net/qjyong/article/details/2158097

http://lavasoft.blog.51cto.com/62575/51926/

http://my.oschina.net/lichhao/blog/111362

http://www.iteye.com/topic/103804

?

用自己的话再解释一下:

每个java.lang.Thread线程类里都有一个ThreadLocalMap成员属性(打开源码就能看见):

ThreadLocal.ThreadLocalMap threadLocals = null;

ThreadLocalMap是ThreadLocal的静态内部类。Thread里的这个threadLocals成员属性就是用来存储各个ThreadLocal的key-value映射的。这里的key就是ThreadLocal对象,值就是ThreadLocal里设定的值。拿上面的代码线程类为例:线程a1中的threadLocals存储了两个key-value对,一个是a(ThreadLocal型)-0(int型),另一个是b(ThreadLocal型)-"a"(字符串型)。线程a2,a3同理。

发表评论
用户名: 匿名