多线程_高级主题_ThreadLocal

这个ThreadLocal表示的是每个线程本地存储区域,也就是每个线程的一亩三分地。可以把ThreadLocal看作是银行,每个银行里面有很多保险箱,每个线程有自己的保险箱,每个客户就相当于每个线程,它内部的存储结构类似于一个map,key是线程的信息,value对应的是存储的内容,也就是数据。这样做的好处是保证了每个线程的数据相互独立,同时又可以共享银行这个大的区域。这样就能达到每个线程级别的数据的存储,达到在多线程环境下保证【成员变量】的安全,因为每个数据只有线程自己能够看得到,别的线程是看不到的,不会影响其他线程。
ThreadLocal官方建议使用private static来修饰,达到线程间共享。
使用ThreadLocal常用的方法有3个:
1、set:设置值
2、get:得到值
3、initialValue:初始化

ThreadLocal后期也会用,一般来说是用在跟每一个线程相关的东西。比如说每一个线程有自己的数据库的连接,这样大家相互不影响;或者我们每一个线程有自己的用户登录信息、用户身份信息、http请求信息,每一个线程是自己的信息。包括我们的高级框架ssh,hibernate里面Session的管理就是使用ThreadLocal,它里面有一个HibernateUtil用的就是ThreadLocal来实现的。或者我们在不同的线程里面设置bean的信息,保证每个线程的bean相互独立,这个Bean就是我们说的java的对象pojo类,存储数据用的,保证我们数据的独立。

多线程_高级主题_ThreadLocal

package com.sxt.others;
/**
 * ThreadLocal:每个线程自身的存储本地、局部区域
 *  get/set/initialValue
 * @author 
 *
 */
public class ThreadLocalTest01 {
	//默认初始值
	//private static ThreadLocal<Integer> threadLocal = new ThreadLocal<> ();
	//更改初始化值
	/*private static ThreadLocal<Integer> threadLocal = new ThreadLocal<> () {
		protected Integer initialValue() {
			return 200;
		}; 
	};*/
	//jdk1.8之后可以这么写
	private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(()-> 200);
	public static void main(String[] args) {
		//获取值
		System.out.println(Thread.currentThread().getName()+"-->"+threadLocal.get());		
		//设置值
		threadLocal.set(99);
		System.out.println(Thread.currentThread().getName()+"-->"+threadLocal.get());
		
		new Thread(new MyRun()).start();
		new Thread(new MyRun()).start();
	}	
	public static  class MyRun implements Runnable{
		public void run() {
			threadLocal.set((int)(Math.random()*99));
			System.out.println(Thread.currentThread().getName()+"-->"+threadLocal.get());		
		}
	}
}



package com.sxt.others;
/**
 * ThreadLocal:每个线程自身的数据,更改不会影响其他线程
 * @author
 *
 */
public class ThreadLocalTest02 {	
	private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(()-> 1);
	public static void main(String[] args) {
		for(int i=0;i<5;i++) {
			new Thread(new MyRun()).start();
		}
	}	
	public static  class MyRun implements Runnable{
		public void run() {
			Integer left =threadLocal.get();
			System.out.println(Thread.currentThread().getName()+"得到了-->"+left);		
			threadLocal.set(left -1);
			System.out.println(Thread.currentThread().getName()+"还剩下-->"+threadLocal.get());	
		}
	}
}



package com.sxt.others;
/**
 * ThreadLocal:分析上下文 环境  起点
 * 1、构造器: 哪里调用 就属于哪里 找线程体
 * 2、run方法:本线程自身的
 * @author 裴新 
 *
 */
public class ThreadLocalTest03 {	
	private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(()-> 1);
	public static void main(String[] args) {
		new Thread(new MyRun()).start();
		new Thread(new MyRun()).start();
	}	
	public static  class MyRun implements Runnable{
		public MyRun() {
			threadLocal.set(-100);
			System.out.println(Thread.currentThread().getName()+"-->"+threadLocal.get());	
		}
		public void run() {
			System.out.println(Thread.currentThread().getName()+"-->"+threadLocal.get());	
			//new Thread(new MyRunxxx()).start();
		}
	}
}



package com.sxt.others;
/**
 * InheritableThreadLocal:继承上下文 环境的数据 ,【拷贝】一份给子线程
 * @author 
 *
 */
public class ThreadLocalTest04 {	
	private static ThreadLocal<Integer> threadLocal = new InheritableThreadLocal<>();
	public static void main(String[] args) {
		threadLocal.set(2);
		System.out.println(Thread.currentThread().getName()+"-->"+threadLocal.get());	
		
		//此线程由main线程开辟
		new Thread(()->{
			System.out.println(Thread.currentThread().getName()+"-->"+threadLocal.get());	
			threadLocal.set(200);
			System.out.println(Thread.currentThread().getName()+"-->"+threadLocal.get());	
		}) .start();
	}
}

注:ThreadLocal就是我们每一个线程自己的局部变量的存储空间,每一个线程都有自己的一亩三分地,可以把它看成是线程本地环境。