一、ThreadLocal
ThreadLocal类用于隔离多线程中使用的对象,为ThreadLocal类中传递的泛型就是要隔离的对象,简单的来说:如果我们在主线程创建了一个对象,并且需要给下面的多线程任务都传递这个对象,那么如果这个对象传递到ThreadLocal,那么每个线程获取的对象都是独立的,不会受其他线程的改变而改变。
ThreadLocal中一共有三个常用方法:
get()方法:获取与当前线程关联的ThreadLocal值。
set(T value)方法:设置与当前线程关联的ThreadLocal值。
initialValue()方法:设置与当前线程关联的ThreadLocal初始值。
我们来看一个列子,创建两个线程,两个线程共同使用一个对象,我们来观察这个对象的值以及ThreadLocal中这个对象的值:
对象User类:
public class User { int num; public User(int num) { this.num = num; } /** * 我们只使用get方法,并且每次获取num都为其加1 * * 使用synchronized保证getNum获取的num是线程安全的 * @return */ synchronized public int getNum() { return num++; } }
线程任务类:
public class ThreadlocaDemo extends Thread{ User user; ThreadlocaDemo(User user){ this.user=user; } /** * 创建一个ThreadLocal对象,为它的泛型传入User */ ThreadLocal<User> userLoacl = new ThreadLocal<User>(){ /** * 初始化方法,将设置user中的初始值 */ @Override protected User initialValue() { User user=new User(10); return user; } }; @Override public void run() { for (int i = 1; i <3 ; i++) { //休息一会儿 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //打印user中获取的值 System.out.println(getName()+"user对象的值"+user.getNum()); //打印ThreadLocal中的user对象的值 System.out.println(getName()+"ThreadLocal中的user对象的值"+userLoacl.get().getNum()); } } }
测试类:
public class Main { public static void main(String[] args) { //创建一个共用的对象 User user=new User(10); //创建两个线程任务 ThreadlocaDemo threadlocaDemo1=new ThreadlocaDemo(user); ThreadlocaDemo threadlocaDemo2=new ThreadlocaDemo(user); threadlocaDemo1.setName("这是1号线程:"); threadlocaDemo2.setName("这是2号线程:"); threadlocaDemo1.start(); threadlocaDemo2.start(); } }
运行的结果:
根据运行结果我们可以清楚的看到,在ThreadLocal中的user对象是隔离的,外面的user对象没有被隔离,被两个线程都进行修改过。