java并发编程(四)之 ThreadLocal实现线程局部变量

一、ThreadLocal 介绍

在并发的情况下,多个线程会同时访问同一个变量,这会引起线程安全问题。而ThreadLocal 针对这种情况就被提了出来。他的思想从他的名字就可以看出来,线程局部(变量),即当多个线程访问同一个变量时,每个线程都会拿到这个变量的一个副本,各个线程操作的各自副本,互不干扰。

二、思想的具体实现

Thread类有一个类型为ThreadLocal.ThreadLocalMap的实例变量threadLocals,也就是说每个线程有一个自己的ThreadLocalMap。ThreadLocalMap有自己的独立实现,可以简单地将它的key视作ThreadLocal,value为代码中放入的值(实际上key并不是ThreadLocal本身,而是它的一个弱引用)。每个线程在往某个ThreadLocal里塞值的时候,都会往自己的ThreadLocalMap里存,读也是以某个ThreadLocal作为引用,在自己的map里找对应的key,从而实现了线程隔离。

三、使用案例

package com.dason.first;

import java.util.Random;

public class ThreadLocalDemo {

	private static ThreadLocal x = new ThreadLocal();
	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();
					System.out.println(Thread.currentThread().getName() 
							+ " has put data :" + data);
					x.set(data);
					new A().get();
					new B().get();
				}
			}).start();
		}
	}
	
	static class A{
		public void get(){
			int data = x.get();
			System.out.println("A from " + Thread.currentThread().getName() 
					+ " get data :" + data);
		}
	}
	
	static class B{
		public void get(){
			int data = x.get();			
			System.out.println("B from " + Thread.currentThread().getName() 
					+ " get data :" + data);			
		}		
	}
}

四、封装

public class ThreadLocalDemo {

	public static void main(String[] args) {
		for(int i=0;i<2;i++){
			new Thread(new Runnable(){
				@Override
				public void run() {
					ThreadLocalValue.getInstance()
						.setName(Thread.currentThread().getName());
					new A().get();
					new B().get();
				}
			}).start();
		}
	}
	
	static class A{
		public void get(){
			ThreadLocalValue myData = ThreadLocalValue.getInstance();
			System.out.println("A from " + Thread.currentThread().getName() 
					+ " getMyData: " + myData.getName());
		}
	}
	
	static class B{
		public void get(){
			ThreadLocalValue myData = ThreadLocalValue.getInstance();
			System.out.println("B from " + Thread.currentThread().getName() 
					+ " getMyData: " + myData.getName());			
		}		
	}
}

class ThreadLocalValue{
	private ThreadLocalValue(){}
	public static ThreadLocalValue getInstance(){
		ThreadLocalValue instance = map.get();
		if(instance == null){
			instance = new ThreadLocalValue();
			map.set(instance);
		}
		return instance;
	}
	private static ThreadLocal map = new ThreadLocal();
	
	private String name;

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

}

五、源码解析

待续。。。

你可能感兴趣的:(Java,Concurrency)