线程局部变量类ThreadLocal

· 在多线程环境下,每个线程都有自己的数据。一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其它线程。
· ThreadLocal可以放一个线程级别的变量,其本身能够被多个线程共享使用,并且又能够达到线程安全的目的。说白了,ThreadLocal就是想在多线程环境下去保证成员变量的安全。常用的方法有get/set/initialValue方法。
· JDK建议ThreadLocal设置为private static。
· ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等,这样一个线程的所有调用到的方法都可以非常方便地访问这些资源。
\quad · Hibernate的Session工具类HibernateUtil。
\quad · 通过不同的线程对象设置Bean属性,保证各个线程Bean对象的独立性。

\quad 可以把ThreadLocal理解为一栋全是相同毛坯房的建筑,在创建线程对象时,每个线程都会给自己拿一间房,线程A调用set方法对ThreadLocal变量值的修改相当于对自己的房子进行装修,这当然仅限于自己的房子,对其它线程的房子没有影响,同理每个线程调用get方法也只能展示自己的房子。
\quad ThreadLocal内部的存储结构类似于Map,Key为线程信息(每个线程都会有唯一的标识),值为存储的数据。

/**
 * ThreadLocal:每个线程自身的存储本地、局部区域
 * get/set/initialValue
 */
public class ThreadLocalTest01 {
    //private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>(); //默认返回值为null
    //使用匿名内部类重写initialValue方法更改初始值
    /*private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>() {
        @Override
        protected Integer initialValue() {
            return 200;
        }
    };*/
    //使用Lambda简写
    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 {
        @Override
        public void run() {
            threadLocal.set((int)(Math.random()*99));
            System.out.println(Thread.currentThread().getName()+"-->"+threadLocal.get());
        }
    }
}

在这里插入图片描述

/**
 * ThreadLocal:每个线程自身的数据,更改不会影响其它线程
 * get/set/initialValue
 */
public class ThreadLocalTest02 {
    private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(()->1);


    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new Thread(new MyRun()).start();
        }
    }

    public static class MyRun implements Runnable {
        @Override
        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());
        }
    }
}

在这里插入图片描述

/**
 * ThreadLocal:分析上下文环境
 * 1、构造器:哪里调用 就属于哪里 找线程体
 * 2、run方法:本线程自身的
 *
 */
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());
        }

        @Override
        public void run() {
        //想想下面的语句中当前线程指的是谁
            System.out.println(Thread.currentThread().getName()+"-->"+threadLocal.get());
        }
    }
}

在这里插入图片描述

/**
 * InheritableThreadLocal:继承上下文环境的数据,拷贝给子线程
 *
 */
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线程开辟,所以继承了main的值
        new Thread(()-> {
            System.out.println(Thread.currentThread().getName()+"-->"+threadLocal.get());
            threadLocal.set(200);
            System.out.println(Thread.currentThread().getName()+"-->"+threadLocal.get());
        }).start();
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值