跳至主要內容

基本使用

mozzie大约 2 分钟JavaJava

基本使用

常用方法

方法描述
ThreadLocal<>()创建 ThreadLocal 对象
protected T initialValue()返回当前线程局部变量的初始值
public void set( T value)设置当前线程绑定的局部变量
public T get()获取当前线程绑定的局部变量
public void remove()移除当前线程绑定的局部变量
public class MyDemo {

    private static ThreadLocal\<String\> tl = new ThreadLocal\<\>();

    private String content;

    private String getContent() {
        // 获取当前线程绑定的变量
        return tl.get();
    }

    private void setContent(String content) {
        // 变量content绑定到当前线程
        tl.set(content);
    }

    public static void main(String[] args) {
        MyDemo demo = new MyDemo();
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    // 设置数据
                    demo.setContent(Thread.currentThread().getName() + "的数据");
                    System.out.println("-----------------------");
                    System.out.println(Thread.currentThread().getName() + "--->" + demo.getContent());
                }
            });
            thread.setName("线程" + i);
            thread.start();
        }
    }
}

应用场景

ThreadLocal 适用于下面两种场景:

  • 每个线程需要有自己单独的实例
  • 实例需要在多个方法中共享,但不希望被多线程共享

ThreadLocal 方案有两个突出的优势:

  1. 传递数据:保存每个线程绑定的数据,在需要的地方可以直接获取,避免参数直接传递带来的代码耦合问题
  2. 线程隔离:各线程之间的数据相互隔离却又具备并发性,避免同步方式带来的性能损失

ThreadLocal 用于数据连接的事务管理:

public class JdbcUtils {
    // ThreadLocal对象,将connection绑定在当前线程中
    private static final ThreadLocal\<Connection\> tl = new ThreadLocal();
    // c3p0 数据库连接池对象属性
    private static final ComboPooledDataSource ds = new ComboPooledDataSource();
    // 获取连接
    public static Connection getConnection() throws SQLException {
        //取出当前线程绑定的connection对象
        Connection conn = tl.get();
        if (conn == null) {
            //如果没有,则从连接池中取出
            conn = ds.getConnection();
            //再将connection对象绑定到当前线程中,非常重要的操作
            tl.set(conn);
        }
        return conn;
    }
	// ...
}

用 ThreadLocal 使 SimpleDateFormat 从独享变量变成单个线程变量:

public class ThreadLocalDateUtil {
    private static ThreadLocal\<DateFormat\> threadLocal = new ThreadLocal\<DateFormat\>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };

    public static Date parse(String dateStr) throws ParseException {
        return threadLocal.get().parse(dateStr);
    }

    public static String format(Date date) {
        return threadLocal.get().format(date);
    }
}
贡献者: mozzie