廖雪峰Java11多线程编程-4线程工具类-1ThreadLocal

多线程是Java实现多任务的基础:java

  • Thread
  • ExecutorService
  • ScheduledThreadPool
  • Fork/Join

Thread对象表明一个线程:调用Tread.currentThread()获取当前线程。
多任务程序一般须要针对每一个任务启动一个新的线程,来处理这个用户的请求,也能够从线程池取出一个空闲的线程来处理。

如何在一个线程内传递状态:
例如咱们在一个线程处理过程当中,常常须要调用不一样的类来处理不一样的功能,咱们如何在这些方法中可以方便的获取到当前的用户?

JDK提供了ThreadLocal在一个线程中传递同一个对象多线程

static ThreadLocal<String> threadLocalUser = new ThreadLocal<>();
    threadLocalUser.set("Bob"); //给当前线程绑定一个指定的值
    ...
    String current = threadLocalUser.get(); //调用get()方法能够在当前线程随时获取到已绑定的这个值
    String current = threadLocalUser.get();
    String current = threadLocalUser.get();
    ...
    threadLocalUser.remove(); //把绑定的值从当前线程中解除

ThreadLocal典型的使用方式:

ThreadLocal必定要在finally中清除。当前线程执行完相关代码之后,颇有可能从新放入线程池中,若是ThreadLocal没有被清除,这个线程在执行其余代码的时候,就会把上一次的状态带进去。this

try{
        UserContext.set(user);
    ...
    }finally{
        UserContext.remove();
    }
class User{ //表示当前的一个用户
    String name;
    int level;
    public User(String name, int level){
        this.name = name;
        this.level = level;
    }
}
class UserContext implements AutoCloseable{
    static final ThreadLocal<User> context = new ThreadLocal<>(); //全局惟一静态变量
    public static User getCurrentUser(){    //获取当前线程的ThreadLocal User
        return context.get();
    }
    public UserContext(User user){ //初始化ThreadLocal的User
        context.set(user);
    }
    public void close(){ //移除ThreadLocal关联的User
        context.remove();
    }
}
class ProcessThread extends Thread{
    User user;
    ProcessThread(User user){ //传入User对象
        this.user = user;
    }
    public void run(){
        try(UserContext ctx = new UserContext(user)){
            new Greeting().hello();
            Level.checkLevel();
        }
    }
}
class Greeting{
    void hello(){
        User user = UserContext.getCurrentUser();
        System.out.println("Hello,"+user.name+"!");
    }
}
class Level{
    static void checkLevel(){
        User user = UserContext.getCurrentUser();
        if(user.level>100){
            System.out.println(user.name+" is a VIP user.");
        }else{
            System.out.println(user.name+" is a registered user.");
        }
    }
}
public class Main{
    public static void main(String[] args) throws Exception{
        Thread t1 = new ProcessThread(new User("Bob",120));
        Thread t2 = new ProcessThread(new User("Alice",80));
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("Main end");
    }
}


能够把ThreadLocal当作全局Map<Thread, Object>:线程

  • 每一个线程获取ThreadLocal变量时,使用Thread自身做为key
Object ThreadLocalValue = threadLocalMap.get(Thread.currentThread());

总结:

  • ThreadLocal表示线程的“局部变量”,它确保每一个线程的ThreadLocal变量都是各自独立的
  • ThreadLocal适合在一个线程的处理流程中保持上下文(避免了同一参数在全部方法中传递)
  • 使用ThreadLocal要用try..finally结构
相关文章
相关标签/搜索