一,线程局部变量ThreadLocal的作用
用于实现线程内部的数据共享,既对于相同的程序代码,多个模块在同一个线程中运行时要共享一份数据,在另一个线程访问的时候,访问的由是另一份数据。
每个线程调用ThreadLocal对象的set方法时,就相当于向内部Map集合中增加一条记录。
Map(key,value)key相当于当前的线程,value相当于set()传递进来的值。
ThreadLocal<T> threadLocal =new ThreadLocal<T>(); T是set()方法传进来的值类型。
问题:一个ThreadLocal中只能存放一个变量,既其中只能存放一个数据,如果由两个数据,可以定义两个ThreadLocal,但是如果有多个呢?例如100个?
解决方法是定义一个对象来存放这100个数据,然后在ThreadLocal中存放这个对象。
二,在 Runnable 中创建 ThreadLocal
在线程类内部创建 ThreadLocal,基本步骤如下:
①、在多线程的类(如 ThreadDemo 类)中,创建一个 ThreadLocal 对象 threadXxx,用来保存线程间需要隔离处理的对象 xxx。
②、在 ThreadDemo 类中,创建一个获取要隔离访问的数据的方法 getXxx(),在方法中判断,若ThreadLocal 对象为 null 时候,应该 new()一个隔离访问类型的对象,并强制转换为要应用的类型
③、在 ThreadDemo 类的 run()方法中,通过调用 getXxx()方法获取要操作的数据,这样可以保证每个线程对应一个数据对象,在任何时刻都操作的是这个对象。
代码:
package com.itheima.gan; import java.util.Random; public class ThreadLocalTest implements Runnable{ //创建一个线程局部变量 ThreadLocal<Student> studentThreadLocal=new ThreadLocal<Student>(); @Override public void run() { //获取当前线程的名字 String currentThreadName=Thread.currentThread().getName(); System.out.println(currentThreadName+" is running ...."); //随机生成一个整数 Random random=new Random(); int age=random.nextInt(100); System.out.println(currentThreadName+" is set age:"+age); //通过这个方法为每一个线程都设置一个独立的student对象 Student student=getStudent(); student.setAge(age); System.out.println(currentThreadName+" is first get age:"+student.getAge()); //线程沉睡 try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } //线程第二次获取年纪 System.out.println(currentThreadName+" is second get age:"+student.getAge()); } private Student getStudent() { //先获取studnet对象 Student student=studentThreadLocal.get(); //判断对象是否为空,是空的话表示没有给局部变量设置,如果是空的话就在给局部变量重新设置一个值 if(student==null) { student=new Student(); studentThreadLocal.set(student); } return student; } public static void main(String[] args) { ThreadLocalTest test=new ThreadLocalTest(); Thread t1=new Thread(test,"线程1"); Thread t2=new Thread(test,"线程2"); t1.start(); t2.start(); } } class Student{ int age; public int getAge() { return age; } public void setAge(int age) { this.age=age; } }
运行结果: