【Java多线程】——ThreadLocal类的用法

    变量值的共享可以通过使用public static的形式,使得一个类的所有实例对象共享类中的同一个变量。但是如果想要实现每个线程都有自己的一个共享变量该如何解决呢?这个时候就要用到ThreadLocal类了。ThreadLocal类就是用来解决每个线程都能绑定自己的值,可以把ThreadLocal类看成一个全局的存放数据的盒子,盒子中可以存放每个线程自己的数据。

一、使用ThreadLocal类

public class Run {
	public static ThreadLocal tl = new ThreadLocal();
	public static void main(String args[]) {
		if(tl.get()==null) {
			System.out.println("ThreadLocal还没有被赋值。");
			tl.set(9527);
		}
		System.out.println(tl.get());
	}
}

运行程序可以看到结果为:

/*

ThreadLocal还没有被赋值。

9527

*/

可以看到,ThreadLocal类中的get方法第一次被调用的时候返回null,而在set之后再调用get方法返回的就是存入的新值了。ThreadLocal主要是为了保证变量在不同线程之间的隔离性,也就是说对于一个变量而言在不同线程内部拥有不同的值,这时就可以用ThreadLocal类来保存这些值。

下面的例子验证了ThreadLocal变量的值在不同线程间的隔离性:

//ThreadLocal类用来创建共享变量
public class Tools {
	public static ThreadLocal tl = new ThreadLocal();
}
public class ThA extends Thread{
	@Override
	public void run() {
		try {
			for(int i=0;i<10;i++) {
				Tools.tl.set("Thread-A="+(i+1));
				System.out.println(Tools.tl.get());
				Thread.sleep(500);
			}
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}
public class ThB extends Thread{
	@Override
	public void run() {
		try {
			for(int i=0;i<10;i++) {
				Tools.tl.set("Thread-B="+(i+1));
				System.out.println(Tools.tl.get());
				Thread.sleep(500);
			}
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}
public class Run {
	public static void main(String args[]) {
		try {
			ThA tha = new ThA();
			ThB thb = new ThB();
			tha.start();
			thb.start();
			for(int i=1;i<10;i++) {
				Tools.tl.set("Thread-Main="+(i+1));
				System.out.println(Tools.tl.get());
				Thread.sleep(500);
			}
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}

部分输出结果为:

/*

Thread-Main=2

Thread-B=1

Thread-A=1

Thread-A=2

Thread-B=2

Thread-Main=3

Thread-A=3

Thread-Main=4

Thread-B=3

Thread-B=4

Thread-A=4

Thread-Main=5

Thread-A=5

Thread-Main=6

*/

可以看到,两个子线程和主线程交替运行,三个线程各自向tl中存入属于自己线程的值,每个线程在调用tl对象的get方法时可以获得相应的自己的值。

ps:上面两个例子ThreadLocal实例化的时候是没有初始值的,也就是说,第一次调用get会返回null。如果想在ThreadLocal创建实例对象的同时初始化它的值,则可以创建一个类继承ThreadLocal,其中重写ThreadLocal类中的initialValue()方法,使其返回我们所需要的初始值即可。

二、InheritableThreadLocal类的值继承

    使用类InheritableThreadLocal类可以实现在子线程中继承来自主线程中的ThreadLocal的值。

//继承InheritableThreadLocal,并重写initialValue方法
public class InheritableThreadLocalExt extends InheritableThreadLocal{
	@Override
	protected Object initialValue() {
		return new Date().getTime();
	}
}
public class Tool {
	public static InheritableThreadLocalExt tl = new InheritableThreadLocalExt();
}
public class ThA extends Thread{
	@Override
	public void run() {
		try {
			for(int i=0;i<3;i++) {
				System.out.println("子线程的值:"+Tool.tl.get());
				Thread.sleep(500);
			}
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}
public class Run {
	public static void main(String args[]) {
		try {
			for(int i=0;i<3;i++) {
				System.out.println("main线程中的值:"+Tool.tl.get());
				Thread.sleep(500);
			}
			Thread.sleep(2000);
			System.out.println("currentTimeMillis="+System.currentTimeMillis());
			ThA tha = new ThA();
			tha.start();
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}

在主线程中,先给获取tl的值并进行打印,然后主线程sleep一段时间,接着创建子线程tha,并启动tha线程输出tha存储在tl中的值。可以看到以下输出结果:

/*

main线程中的值:1526630816087

main线程中的值:1526630816087

main线程中的值:1526630816087

currentTimeMillis=1526630819597

子线程的值:1526630816087

子线程的值:1526630816087

子线程的值:1526630816087

*/

子线程继承了主线程中的InheritableThreadLocal中的值。

如果不想让子线程继承主线程中的共性变量的值,只需要在InheritableThreadLocalExt中重写以下方法:

@Override
protected Object childValue(Object parentValue) {
	return parentValue+"子线程重新初始化";
}

则从子线程中获取tl共享变量的值时,将不再和主线程中的值一样。

ps:如果子线程在取得值的同时,主线程中对InheritableThreadLocal中的值进行了修改,则子线程中的值不同步更新,依然取到的是旧的值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值