ThreadLocal深入理解

JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序,ThreadLocal并不是一个Thread,而是Thread的局部变量

在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。

我们来看一个示例吧

import java.util.Random;

/**
 * ThreadLocal的深入理解
 * 
 * @author chinoukin
 *
 */
public class ThreadLocalTest {

	private static ThreadLocal x = new ThreadLocal<>();

	public static void main(String[] args) {
		new Thread(new Runnable() {

			@Override
			public void run() {
				int data = new Random().nextInt();
				x.set(data);
				System.out.println(Thread.currentThread().getName() + "放入id:" + data);

				MyLocalData myLocalData = MyLocalData.getMyLocalDataInstance();
				myLocalData.setId(data);
				myLocalData.setName("张三丰");

				new TestA().get();
				new TestB().get();

			}

		}, "线程1").start();

		new Thread(new Runnable() {

			@Override
			public void run() {
				int data = new Random().nextInt();
				x.set(data);
				System.out.println(Thread.currentThread().getName() + "放入id:" + data);

				MyLocalData myLocalData = MyLocalData.getMyLocalDataInstance();
				myLocalData.setId(data);
				myLocalData.setName("张无忌");

				new TestA().get();
				new TestB().get();
			}

		}, "线程2").start();
	}

	static class TestA {
		public void get() {
			int data = x.get();
			MyLocalData myLocalData = MyLocalData.getMyLocalDataInstance();
			System.out.println("A从" + Thread.currentThread().getName() + "中拿出id:" + data);
			System.out.println("A从" + Thread.currentThread().getName() + "中拿出name:" + myLocalData.getName());
		}
	}

	static class TestB {
		public void get() {
			int data = x.get();
			MyLocalData myLocalData = MyLocalData.getMyLocalDataInstance();
			System.out.println("B从" + Thread.currentThread().getName() + "中拿出id:" + data);
			System.out.println("B从" + Thread.currentThread().getName() + "中拿出name:" + myLocalData.getName());
		}
	}
}

/**
 * 线程数据类(ThreadLocal) 每一个线程最多只有一个实例,保证每个线程自己数据类实例不会被其他线程破坏
 * 
 * @author chinoukin
 *
 */
class MyLocalData {
	private MyLocalData() {
	}

	private static ThreadLocal map = new ThreadLocal<>();

	public static MyLocalData getMyLocalDataInstance() {
		MyLocalData myLocalData = map.get();
		if (myLocalData == null) {
			myLocalData = new MyLocalData();
			map.set(myLocalData);
		}
		return myLocalData;
	}

	private int id;
	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

运行结果:

线程1放入id:569578798
线程2放入id:-185649376
A从线程1中拿出id:569578798
A从线程2中拿出id:-185649376
A从线程1中拿出name:张三丰
A从线程2中拿出name:张无忌
B从线程2中拿出id:-185649376
B从线程2中拿出name:张无忌
B从线程1中拿出id:569578798
B从线程1中拿出name:张三丰
通过执行结果我们可以发现,每个线程自己的ThreadLocal变量都是独立的,线程间互补干扰。





你可能感兴趣的:(java基础)