多线程与并发-----ThreadLocal类及应用技巧

多个模块在同一个线程中运行时要共享同一份数据,实现线程范围内的数据共享可以用Map。

JDK1.5提供了ThreadLocal类来方便实现线程范围内的数据共享,它的作用就相当于Map

每个线程调用全局ThreadLocal对象的set方法,就相当于往其内部的map集合中增加一条记录,key就是各自的线程,value就是各自的set方法传进去的值。

在线程结束时可以调用ThreadLocal.clear()方法用来更快释放内存,也可以不调用,因为线程结束后也可以自动释放相关的ThreadLocal变量。

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class ThreadLocalTest {
	
	private static ThreadLocal<Integer> threadLocal=new ThreadLocal<Integer>();
	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();
					//Thread.currentThread()获取当前线程。
					System.out.println(Thread.currentThread().getName()+" has put data:"+data);
					//将线程信息和对应数据存储起来
					threadLocal.set(data);
					//使用两个不同的模块操作这个数据,看结果
					new A().get();
					new B().get();
				}
			}).start();
		}
	}
	
	static class A{
		public void get(){
			int data=threadLocal.get();
			System.out.println("A from"+Thread.currentThread().getName()+" get data:"+data);
		}
	}
	
	static class B{
		public void get(){
			int data=threadLocal.get();
			System.out.println("B from"+Thread.currentThread().getName()+" get data:"+data);
		}
	}
	
}

运行结果为:

Thread-0 has put data:-1595352605
Thread-1 has put data:-765849300
A fromThread-0 get data:-1595352605
A fromThread-1 get data:-765849300
B fromThread-0 get data:-1595352605
B fromThread-1 get data:-765849300 


一个ThreadLocal对象只能记录一个线程内部的一个共享变量,需要记录多个共享数据,可以创建多个ThreadLocal对象,或者将这些数据进行封装,将封装后的数据对象存入ThreadLocal对象中。

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class ThreadLocalTest {
	
	private static ThreadLocal<Integer> threadLocal=new ThreadLocal<Integer>();
	
	private static ThreadLocal<MythreadScopeData> mythreadScopeData=new ThreadLocal<MythreadScopeData>();
	
	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();
					//Thread.currentThread()获取当前线程。
					System.out.println(Thread.currentThread().getName()+" has put data:"+data);
					//将线程信息和对应数据存储起来
					threadLocal.set(data);
					
					MythreadScopeData mData=new MythreadScopeData();
					mData.setName("name:"+data);
					mData.setAge(data);
					mythreadScopeData.set(mData);
					//使用两个不同的模块操作这个数据,看结果
					new A().get();
					new B().get();
				}
			}).start();
		}
	}
	
	static class A{
		public void get(){
			int data=threadLocal.get();
			System.out.println("A from"+Thread.currentThread().getName()+" get data:"+data);
			
			MythreadScopeData mData=mythreadScopeData.get();	
			System.out.println("A from"+Thread.currentThread().getName()
					+" getMyData:"+mData.getName()+","+mData.getAge());
		}
	}
	
	static class B{
		public void get(){
			int data=threadLocal.get();
			System.out.println("B from"+Thread.currentThread().getName()+" get data:"+data);
			
			MythreadScopeData mData=mythreadScopeData.get();
			System.out.println("B from"+Thread.currentThread().getName()
					+" getMyData:"+mData.getName()+","+mData.getAge());
		}
	}
	
}

class MythreadScopeData{
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
}

   运行结果为:

Thread-0 has put data:1785375164
Thread-1 has put data:1981597103
A fromThread-0 get data:1785375164
A fromThread-1 get data:1981597103
A fromThread-0 getMyData:name:1785375164,1785375164
A fromThread-1 getMyData:name:1981597103,1981597103
B fromThread-0 get data:1785375164
B fromThread-1 get data:1981597103
B fromThread-0 getMyData:name:1785375164,1785375164

B fromThread-1 getMyData:name:1981597103,1981597103

将上述代码进行优化:

        将数据对象封装成单例,同时提供线程范围内的共享数据的设置和获取方法,提供已经封装好了的线程范围内的对象实例,使用时只需获取实例对象即可实现数据的线程范围内的共享,因为该对象已经是当前线程范围内的对象了。

         演示代码如下: 

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class ThreadLocalTest {
	
	private static ThreadLocal<Integer> threadLocal=new ThreadLocal<Integer>();
	
	private static ThreadLocal<MythreadScopeData> mythreadScopeData=new ThreadLocal<MythreadScopeData>();
	
	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();
					//Thread.currentThread()获取当前线程。
					System.out.println(Thread.currentThread().getName()+" has put data:"+data);
					//将线程信息和对应数据存储起来
					threadLocal.set(data);
					
					/*
					MythreadScopeData mData=new MythreadScopeData();
					mData.setName("name:"+data);
					mData.setAge(data);
					mythreadScopeData.set(mData);
					*/
					MythreadScopeData.getThreadInstance().setName("name:"+data);
					MythreadScopeData.getThreadInstance().setAge(data);
					
					//使用两个不同的模块操作这个数据,看结果
					new A().get();
					new B().get();
				}
			}).start();
		}
	}
	
	static class A{
		public void get(){
			int data=threadLocal.get();
			System.out.println("A from "+Thread.currentThread().getName()+" get data:"+data);
			
			/*MythreadScopeData mData=mythreadScopeData.get();	
			System.out.println("A from"+Thread.currentThread().getName()
					+" getMyData:"+mData.getName()+","+mData.getAge());*/
			
			MythreadScopeData mData=MythreadScopeData.getThreadInstance();
			System.out.println("A from "+Thread.currentThread().getName()
					+" getMyData:"+mData.getName()+","+mData.getAge());
		}
	}
	
	static class B{
		public void get(){
			int data=threadLocal.get();
			System.out.println("B from "+Thread.currentThread().getName()+" get data:"+data);
			
			/*MythreadScopeData mData=mythreadScopeData.get();	
			System.out.println("B from"+Thread.currentThread().getName()
					+" getMyData:"+mData.getName()+","+mData.getAge());*/
			
			MythreadScopeData mData=MythreadScopeData.getThreadInstance();
			System.out.println("B from "+Thread.currentThread().getName()
					+" getMyData:"+mData.getName()+","+mData.getAge());
		}
	}
	
}

class MythreadScopeData{
	private MythreadScopeData(){}
	//创建单例模式
	/*
	//方法一
	public static MythreadScopeData getInstance(){
		return instance;
	}
	private static MythreadScopeData instance=new MythreadScopeData();
	
	//方法二
	public static synchronized MythreadScopeData getInstance(){
		if(instance==null){
			instance =new MythreadScopeData();
		}
		return instance;
	}
	private static MythreadScopeData instance=null;
	*/
	
	//仿照单例模式,建立单例线程
	public static MythreadScopeData getThreadInstance(){
		MythreadScopeData instance=map.get();
		if(instance==null){
			instance =new MythreadScopeData();
			map.set(instance);
		}
		return instance;
	}
	private static ThreadLocal<MythreadScopeData> map=new ThreadLocal<MythreadScopeData>();
	
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
}

运行结果为:

Thread-1 has put data:-594509613
Thread-0 has put data:-395209683
A from Thread-1 get data:-594509613
A from Thread-0 get data:-395209683
A from Thread-1 getMyData:name:-594509613,-594509613
A from Thread-0 getMyData:name:-395209683,-395209683
B from Thread-1 get data:-594509613
B from Thread-0 get data:-395209683
B from Thread-1 getMyData:name:-594509613,-594509613
B from Thread-0 getMyData:name:-395209683,-395209683



猜你喜欢

转载自blog.csdn.net/pengzhisen123/article/details/80278520
今日推荐